How to Decode a JWT
Decode a JSON Web Token into header and payload JSON, read exp and iat claims, and understand why decoding is not signature verification.
Decode the two JSON segments — leave the signature alone
A compact JWT is three Base64URL pieces separated by dots: header.payload.signature. To decode it, split on ., Base64URL-decode the first two segments, and parse each result as JSON. The third segment is a cryptographic signature. Reading it as text does not prove the token is authentic.
If you want that inspection without uploading a token, paste it into the JWT Decoder & Inspector. Decoding runs in your browser. The page will not mark a signature as verified.
What a compact JWT looks like
Most access tokens you copy from an Authorization: Bearer header use JWS compact serialization (RFC 7519). Three segments, no whitespace:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhY2N0LTEwNDIiLCJuYW1lIjoiUHJpeWEgU2hhaCIsImlzcyI6Imh0dHBzOi8vYXV0aC5leGFtcGxlLmNvbSIsImlhdCI6MTcxOTc5MjAwMCwiZXhwIjoxNzE5Nzk1NjAwfQ.bm90LWEtcmVhbC1zaWduYXR1cmUStep 1 — Split on dots
Count the dots. A typical signed JWT (JWS) has exactly two dots and three segments. A compact JWE (encrypted token) has five segments; you can read its header, but you cannot decrypt the payload without the key.
- Segment 1 — JOSE header (
alg, oftentyp) - Segment 2 — payload (claims)
- Segment 3 — signature (integrity check, not JSON)
Step 2 — Base64URL-decode header and payload
JWT uses Base64URL (RFC 7515), not standard Base64. The alphabet replaces + with - and / with _, and padding = is usually omitted. Feeding a JWT segment into a generic Base64 decoder often fails for that reason.
After decoding, you should get JSON objects. Header for the sample above:
{
"alg": "HS256",
"typ": "JWT"
}Step 3 — Read the payload claims
The payload is also a JSON object. Registered claim names are defined in RFC 7519. Applications add their own claims on top.
{
"sub": "acct-1042",
"name": "Priya Shah",
"iss": "https://auth.example.com",
"iat": 1719792000,
"exp": 1719795600
}| Claim | Meaning |
|---|---|
| iss | Issuer — who created the token |
| sub | Subject — who the token is about |
| aud | Audience — which API or app should accept it |
| exp | Expiration time as Unix seconds (UTC) |
| nbf | Not-before time; reject the token before this instant |
| iat | Issued-at time |
| jti | JWT ID — a unique identifier for this token |
How to read exp and iat
Time claims are NumericDate values: Unix seconds since 1970-01-01T00:00:00Z, not milliseconds and not ISO-8601 strings. In the sample, iat is 1719792000 (1 July 2024 00:00 UTC) and exp is one hour later.
If a date looks decades off, you probably treated seconds as milliseconds (or the reverse). Convert the number with the Unix Timestamp Converter, or read What Is a Unix Timestamp?.
Decoding is not verification
Anyone who has the token can decode the header and payload. Integrity comes from verifying the signature with the issuer’s secret (HMAC) or public key (RSA/ECDSA). A decoder that only Base64URL-decodes JSON cannot tell a real token from one you edited in a text editor.
Never treat a readable payload as proof that the token is valid. For production auth, verification belongs in your API or identity library — not in a browser inspector.
Common mistakes
These are the failures that show up first when a paste “won’t decode.”
- Leaving the
Bearerprefix on the token. Strip scheme labels before splitting. - Decoding with standard Base64 instead of Base64URL.
- Assuming three segments means the signature was checked.
- Comparing
exptoDate.now()without multiplying seconds by 1000 in JavaScript. - Pasting a live access token into a third-party website. Prefer a local decoder; Toolshelf does not upload the token.
Inspect a token in the browser
Open the JWT Decoder & Inspector, paste the compact token, and decode it. You will see header JSON, payload JSON, and human-readable iat / exp / nbf times. Use JSON Formatter if you need to pretty-print a claim object you copied out, and Base64 Encoder & Decoder if you are learning Base64URL separately.
Frequently asked questions
- How do I decode a JWT payload?
- Split the token on dots, Base64URL-decode the second segment, and parse the result as JSON. That payload is readable; it is not signature-verified.
- Why does my JWT fail to decode?
- Typical causes are a Bearer prefix, extra whitespace or quotes, standard Base64 instead of Base64URL, or a JWE (five segments) whose payload is encrypted.
- Can I decode a JWT without the secret?
- Yes. The header and payload of a compact JWS are encoded, not encrypted. The secret or private key is required to verify the signature, not to read the JSON.
- Is it safe to paste a JWT into an online decoder?
- Treat tokens as secrets. Prefer a decoder that runs in your browser and does not upload the token. Still avoid pasting live production tokens into screenshots or tickets.