esc

JWT Decoder

Decode JSON Web Tokens online, inspect header and payload claims, check expiry and verify supported HMAC signatures locally.

Encoded
Header Payload Signature
Decoded
Valid JWT — — — parts
Claims
Signature
—

Decoding never checks the signature — anyone can read an unverified token. For HMAC tokens (HS256 / HS384 / HS512) you can verify it below; your secret is used only in the browser and is never sent anywhere. RSA / ECDSA tokens need the issuer's public key and aren't verifiable here.

Guide

Anatomy of a JSON Web Token

A JWT is three Base64URL-encoded segments joined by dots: header.payload.signature. The header names the signing algorithm (alg) and token type (typ); the payload carries the claims — standard ones like iss, sub, exp plus any custom fields; the signature is computed over the first two segments so the token can't be tampered with undetected.

A JWT decoder is useful for reading authentication claims, debugging expiry, checking issuer and audience values, and confirming which algorithm a token declares. Decoding is not the same as verifying. The header and payload are merely encoded, not encrypted — anyone can read them, which is why you should never put secrets in a JWT. Only checking the signature against the issuer's key proves the token is authentic and unaltered. This tool decodes everything client-side and can verify HMAC signatures locally; the token never leaves your machine.

Example

JWT decoder example

Many HS256 tokens start with the same first segment, eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 , because it is simply the Base64URL form of this common header — which is also why so many JWTs begin with eyJ, the encoding of {":

{
  "alg": "HS256",
  "typ": "JWT"
}

A typical access-token payload decodes to something like:

{
  "iss": "https://auth.example.com",
  "sub": "user-1234",
  "aud": "api.example.net",
  "iat": 1767225600,
  "exp": 1767229200,
  "scope": "read:reports"
}

The status bar shows the algorithm (HS256), the type ( JWT ), the number of segments and an Active or Expired tag. In the Claims panel, iat is rendered as Thu, 01 Jan 2026 00:00:00 GMT and exp as Thu, 01 Jan 2026 01:00:00 GMT , each followed by a relative time such as “in 5 minutes” or “2 hours ago” — so this token was valid for one hour. scope is listed as a custom claim. Use Load sample to fill in a demo HS256 token together with its secret and try the Verify button.

Claims

Registered JWT claims explained

Claim Meaning What the decoder shows
iss Issuer — the service that created the token The raw value
sub Subject — usually a user or client ID The raw value
aud Audience — the API or app the token is meant for (string or array) The raw value; arrays are shown as JSON
exp Expiration time, in Unix seconds UTC date, relative time and an Active / Expired tag
nbf Not before — the token must be rejected earlier than this UTC date, relative time and a Not yet valid tag when it is in the future
iat Issued at, in Unix seconds UTC date and relative time
jti JWT ID — a unique identifier, often used to block replay The raw value

Registered claims are listed first, followed by every other field as a custom claim (for example scope, role or email). Time claims are seconds since 1970-01-01 UTC, not milliseconds; the Unix timestamps guide explains the format, and the Timestamp Converter converts individual values.

Signatures

JWT algorithms and signature verification

The alg header names how the signature was produced. This page can verify only the HMAC family:

alg Type Key needed Verify here?
HS256, HS384, HS512 HMAC with SHA-2 Shared secret Yes, in the browser via Web Crypto
RS256, PS256, ES256, EdDSA and variants RSA, RSA-PSS, ECDSA, EdDSA Issuer's public key (often from a JWKS URL) No — decode only
none Unsecured token None — there is no signature No — never reported as verified

Decoding is not verification

The green Valid JWT verdict means only that the header and payload are well-formed Base64URL-encoded JSON. Anyone can edit a payload, re-encode it and paste it here; it will decode just as cleanly. Only a matching signature, checked with the right key, shows the token was issued by the expected party and not altered.

Why alg=none is dangerous

A token with "alg": "none" carries no signature, so anyone can mint one with any claims. A server must never accept it, and should not let the token's own header choose the algorithm: configure the expected algorithm (and key) on the verifier. The same rule prevents algorithm confusion, where an RS256 public key is misused as an HS256 secret.

Use cases

When to use a JWT decoder

  • Debugging 401 responses — check whether exp has passed, nbf is still in the future, or aud and iss differ from what the API expects.
  • Reviewing an integration — confirm which alg an identity provider uses and which custom claims (roles, scopes, tenant IDs) it adds.
  • Testing your own HMAC tokens — verify that a development token was signed with the secret you think it was.
  • Checking token hygiene — make sure no emails, internal IDs or other sensitive values leak into a payload that every client can read.
Troubleshooting

Troubleshooting JWT decoding

Symptom Likely cause Fix
“A JWT needs at least 2 dot-separated segments” Only part of the token was copied, or it is an opaque (non-JWT) access token Copy the full value; opaque tokens can only be inspected by their issuer
“Header is not valid Base64URL-encoded JSON” A Bearer prefix, surrounding quotes or a cookie name was pasted with the token Paste only the part starting with eyJ
“Payload is not valid Base64URL-encoded JSON” Truncated token, or an encrypted JWE (five segments) Re-copy the token; a JWE must be decrypted by its recipient
“Signature does not match” with the right secret The secret is stored Base64-encoded, or has extra whitespace Paste the secret exactly as the signer uses it; this tool treats it as UTF-8 text
Expired here, but the API still accepts it Your device clock differs, or the server allows clock-skew leeway Compare exp with the current Unix time
Dates tens of thousands of years in the future Time claims written in milliseconds instead of seconds Fix the issuer to use seconds, as the JWT spec requires
Limitations

JWT decoder limitations

  • Signature verification covers HS256, HS384 and HS512 only. RSA, RSA-PSS, ECDSA and EdDSA tokens are decoded but not verified, and keys cannot be fetched from a JWKS endpoint.
  • Encrypted tokens (JWE) are not decrypted, and only the compact header.payload.signature form is supported, not the JSON serialization.
  • The time tags compare exp and nbf with your device clock, without leeway, and only when they are numbers. iat is displayed but not checked.
  • iss, aud and custom claims are shown, not validated — the decoder cannot know which values your API expects. A verified signature also does not mean the token is unexpired.
FAQ

Frequently asked questions

Is my token sent to a server?

No. Splitting, Base64URL decoding, claim inspection and supported HMAC signature checks run in your browser. Nothing is uploaded, but avoid pasting sensitive production tokens on shared or untrusted devices.

Does decoding verify the signature?

No. Decoding only reads the header and payload. A JWT can be readable yet forged. Use the Signature panel to verify HMAC tokens against the shared secret; RSA and ECDSA tokens require the issuer public key and are not verified here.

Why does it say my token is expired?

The exp claim is a Unix timestamp in seconds. If it is in the past, the token is expired. The nbf claim means not before; if it is in the future, the token is not valid yet. The check uses your device clock.

Should I put sensitive data in a JWT?

No. The header and payload are Base64URL-encoded, not encrypted. Anyone holding the token can read those claims, so keep passwords, API keys and private personal data out of JWT payloads.

Can this tool decode encrypted JWTs (JWE)?

No. A JWE has five segments and its content is encrypted, so the decoder reports that the payload is not valid Base64URL-encoded JSON. Only the intended recipient, holding the decryption key, can read it.