How to Decode a JWT Safely

Updated 2026-08-31 · 3 min read

The three parts of a JWT

A signed JWT is header.payload.signature, each Base64URL-encoded. The header names the algorithm (alg) and key id (kid), the payload carries claims, and the signature proves the token was issued by someone holding the key.

Claims you should always check

Decoding is not verifying

Anyone can rewrite a payload and re-encode it. Only signature verification with the shared secret or the issuer's public key (JWKS) makes claims trustworthy — and that must happen server-side. Never grant access based on a decoded payload in the browser.

Debug a token without leaking it

Paste the token into the JWT Decoder: it prints the header and payload as formatted JSON and tells you whether the token has expired. Decoding runs locally in your browser with no network request. To convert raw exp values by hand, use the Unix Timestamp Converter.

Reading a token by hand

A JWT is three Base64URL segments separated by dots. Split on the dots, Base64URL-decode the first two, and you have two JSON documents. The third segment is binary signature material and will look like noise — that is expected.

Base64URL differs from standard Base64: + becomes -, / becomes _, and padding is dropped. A decoder that does not account for this fails on roughly a quarter of tokens, which is why generic Base64 tools sometimes produce truncated output.

Verification, step by step

Trustworthy verification on the server always performs the same checks in the same order. Skipping any one of them has caused real breaches:

Classic JWT vulnerabilities

The alg: none attack strips the signature and sets the algorithm to none; libraries that honour it accept forged tokens. The algorithm-confusion attack takes an RS256 public key, which is not secret, and submits an HS256 token signed with that public key as the HMAC secret — servers that pick the algorithm from the token accept it.

Both are defeated by the same rule: the server decides the algorithm and the key, the token never does.

Access tokens, refresh tokens and revocation

A signed JWT is valid until it expires and cannot be recalled, which is the fundamental trade-off of stateless auth. Keep access tokens short-lived (5–15 minutes) so the damage window from a leak is small, and keep the refresh token in server-side storage where it can be revoked and rotated on every use.

If you need instant revocation of access tokens, you need server state — a deny-list keyed by token id (jti), checked on every request. At that point be honest about whether opaque session tokens would serve you better.

What belongs in a payload

Payloads are readable by anyone holding the token, so they must never contain passwords, API keys, full personal records or anything covered by data-protection rules. Put a user id, a role or scope list, and the standard time and audience claims — nothing else.

Size matters too: tokens travel on every request, often in a header with a practical limit around 8 KB. Embedding a large permission matrix in the payload slows every single call your users make.

Common JWT problems

A token that works locally but fails in production usually means a different signing key or issuer per environment. alg: none tokens must always be rejected. If the payload is unreadable, you likely have an encrypted JWE rather than a signed JWS.

Try the JWT Decoder →Decode a JWT online to read its header, payload claims and expiry status. Free JWT decoder that runs 100% in your browser — tokens are never uploaded.

Frequently asked questions

How long should an access token live?

Commonly 5–15 minutes, paired with a longer-lived refresh token that can be revoked.

Should JWTs be stored in localStorage?

An httpOnly, secure cookie is safer because JavaScript — and therefore XSS — cannot read it.

Can I trust claims after decoding a token in the browser?

No. Decoding proves nothing. Only server-side signature verification makes claims trustworthy.

What is the kid header for?

It identifies which key from the issuer's JWKS signed the token, so issuers can rotate keys without invalidating everything at once.

Why is my payload unreadable after decoding?

You likely have an encrypted JWE (five segments) rather than a signed JWS (three segments); JWE requires the decryption key.

More guides

Decoding vs Verifying a JWTDecoding a JWT reads its claims; verifying it proves the token is authentic. See the difference with a worked example, the claims that matter, and common auth mistakes.HTML Entities and EscapingLearn when to escape HTML, which characters need entities, how encoding helps prevent XSS, and when decoding HTML entities is safe.How to Convert JSON to CSVConvert JSON arrays and objects into CSV for spreadsheets, databases, and reports, including headers, nested values, and escaping rules.URL Encoding Query ParametersLearn why URLs need percent encoding, which characters break query strings, and when to use encodeURIComponent instead of encodeURI.