Skip to content
JWT toolkit

JWT decoder online

Decoder for JWT tokens: split into header, payload and signature, base64url decode, JSON parsing, claim explainer for every standard claim (iss, sub, aud, exp, iat, nbf, jti) and for the custom claims of the most common IdPs, live expiry countdown, side-by-side comparison of multiple tokens, optional HS256 signature verification via WebCrypto if you have the secret. For security analysis (alg=none detection, weak HS256, missing claims, oversized lifetime) the dedicated tool is the JWT security audit.

How to use the decoder

  1. 1

    Paste the JWT

    Three parts separated by dots: header.payload.signature. The decoder accepts standard JWS (signed). It does NOT accept JWE (encrypted, 5 segments).

  2. 2

    Read the sections

    Decoded header: alg + typ + kid if present. Decoded payload: all claims as pretty-printed JSON. Signature: base64url string (not decoded - those are raw bytes).

  3. 3

    Claim explainer

    For each standard RFC 7519 claim (iss, sub, aud, exp, iat, nbf, jti) the decoder shows meaning and expected format. For custom claims (e.g. roles, permissions, tenant_id) it shows the raw value.

  4. 4

    Expiry countdown

    If payload has exp: live countdown to expiry, with 'active' / 'expired N min ago' status. Useful for debugging tokens rejected server-side without clear reason why.

What it solves, in practice

Structured reading of the payload. The decoder splits the token into the three standard parts, decodes base64url, parses JSON and shows the payload pretty-printed. For each RFC 7519 standard claim (iss, sub, aud, exp, iat, nbf, jti) the value is presented with the meaning and expected format; for the most recurring custom claims across IdPs (scope, roles, permissions, tenant_id, cognito_groups, Auth0 namespaced claims) the same contextual explanation.

Operational use cases. Debugging an API that rejects a token, to check that the claims match what the server expects. Verifying lifetime: an exp in the past is the most frequent cause of 401 in E2E tests and not always evident at first reading; the live countdown shows it immediately. Understanding custom claims emitted by IdPs you don't deal with daily (Auth0, Okta, AWS Cognito, Keycloak, Azure AD), in particular namespaced claims of the form https://example.com/roles. Side-by-side comparison between consecutive tokens of an OAuth flow (id_token, access_token, refresh_token) to highlight the differences.

Optional HS256 signature verification. If you have the server-side secret for an HS256 token, paste it in the dedicated field and verify the signature directly via WebCrypto. The HMAC-SHA256 computation happens in the browser; the secret is not transmitted to any endpoint. For RS256/ES256 tokens, where verification requires the IdP public key and JWKS fetch, the right analysis is the JWT security audit.

RFC 7519 standard claims

iss (issuer)
Canonical URL of the IdP that issued the token. Example: https://accounts.google.com, https://login.microsoftonline.com/{tenant_id}/v2.0. Validate backend-side: must match a trusted IdP.
sub (subject)
Token subject (user) identifier. Typically UUID, email, internal ID. Stable across consecutive tokens for the same user.
aud (audience)
Token recipient identifier. Backend must verify it's in aud: prevents confused deputy attack (token for service A forwarded to service B).
exp (expiration)
Unix timestamp (seconds, not ms!) of expiration. Backend must reject tokens with exp < now. Typically 15-60 min for access tokens, hours-days for refresh.
iat (issued at)
Unix timestamp of issuance. Lets you compute token age and implement temporal blacklists.
nbf (not before)
Unix timestamp before which the token is NOT valid. Rare, used for deferred tokens. Backend must reject tokens with nbf > now.
jti (JWT ID)
Unique token identifier (UUID). Used for anti-replay (server-side blacklist on first use, typical for refresh token rotation).

Glossary

Technical terms used on this page, briefly explained.

JWT #
JSON Web Token, RFC 7519. String header.payload.signature, each base64url-encoded. Standard for modern API authentication.
JWS / JWE #
JSON Web Signature (JWS, signed-only, 3 segments) vs JSON Web Encryption (JWE, encrypted, 5 segments). This decoder handles only JWS. JWE requires a key to decrypt.
base64url #
Base64 variant (RFC 4648 sec. 5) with url-safe characters: - instead of +, _ instead of /, no = padding. Used in JWT to avoid extra URL-encoding.
Claim #
Key-value pair in the JWT JSON payload. Standard RFC 7519: iss, sub, aud, exp, iat, nbf, jti. Custom: anything else (e.g. roles, permissions, tenant_id).
Multi-token comparison #
Side-by-side comparison of two or more JWTs. Typical for debugging OAuth flows with id_token + access_token + refresh_token.
Expiry countdown #
Live visualization of remaining time to token expiration. Useful to catch already-expired tokens (common cause of 401 errors in production).

Frequently asked questions

Decoder vs audit: which one do I use?
Decoder to read JWT contents (debug, inspection, understanding). Audit to identify security vulnerabilities (alg=none, weak secret, missing claims). Complementary: decoder shows what's in the token, audit tells you whether there are problems.
Does the decoder verify the signature?
Optionally yes for HS256 tokens, if you paste the server-side secret in the dedicated field: HMAC-SHA256 verification happens via WebCrypto directly in the browser. For RS256, ES256 and other asymmetric algorithms, verification requires the IdP public key and a JWKS fetch: use your IdP's official SDK in debug mode, or switch to the JWT security audit for the full security analysis.
I get 'invalid token': what should I check?
Verify: (1) three parts separated by dots (header.payload.signature). (2) each part is valid base64url. (3) header and payload are valid JSON. Common errors: token cut off in copy-paste; spaces/newlines in the middle (remove them); JWE instead of JWS (5 segments, JWE decoder needed).
How do I compare two tokens side-by-side?
Decode the first, copy the JSON payload. Decode the second. Open a text diff tool (e.g. the diff tool on this site) and paste both payloads. Obvious differences: typically exp, iat, scope/permissions distinct between access and id tokens.
Can I decode an Auth0/Okta/AWS Cognito token?
Yes. All modern OAuth/OIDC providers (Auth0, Okta, AWS Cognito, Azure AD, Keycloak, Google Identity, Facebook Login) emit standard JWS JWTs. The decoder works with any issuer.
The payload has a namespaced claim like 'https://example.com/roles': what is it?
Auth0/IdP convention for custom claims that don't conflict with RFC. Auth0 recommends HTTPS-style namespaces to avoid collisions with future standard claims. The value below is app-specific: roles, permissions, tenant_id, etc. The decoder shows it raw - you interpret meaning by context.
Expiry countdown shows 'expired' but the backend accepts it: bug?
Possible causes: (1) server-side clock skew (server with skewed clock accepts slightly 'expired' tokens); (2) configured tolerance (e.g. AWS Cognito accepts tokens up to 10s expired); (3) backend uses iat and a sliding window instead of strict exp. Verify with the backend: the rule 'exp < now -> 401' is not universal.
Can I paste a JWT with BOM or whitespace at the borders?
Yes, the decoder does trim() before parsing. UTF-8 BOM is stripped. Spaces and newlines INSIDE one of the 3 parts however break parsing: copy/paste carefully. If the JWT comes from terminal output, watch out for automatic line wrap.

Are you integrating JWT in a production app?

I can audit your JWT implementation (key rotation, claims validation, refresh tokens, blacklist, security scope) and recommend the right library for your stack. PHP, Laravel, Symfony, Node, Python backends.

Audit your JWT implementation