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

How Many Words Is a 5-Minute Speech?A 5-minute speech is roughly 625–750 words at a normal speaking pace. See word counts for 1, 3, 5, 10 and 20-minute talks, plus how to check yours instantly.How to Validate JSON and Fix Common Syntax ErrorsLearn how to validate JSON and fix the most common errors: trailing commas, single quotes, unquoted keys, comments and unescaped characters — with examples.Base64 Is Not Encryption: What It Actually DoesBase64 is reversible encoding, not encryption. Learn what Base64 is for, when to use it, its 33% size cost, and safe alternatives for protecting data.SEO-Friendly URL Structure: Rules and ExamplesHow to structure URLs for SEO: slug length, hyphens vs underscores, stop words, trailing slashes, parameters and safe URL changes with redirects.