🔑 JWT Decoder

Decode JSON Web Tokens — see header, payload, and expiration

✓ Free Forever · ✓ No Signup · ✓ No Upload · ✓ Works Offline

🔒 Your data never leaves your device. All processing happens locally in your browser using JavaScript Base64 decoding. No upload, no server, no tracking.

Features

  • Full Token Inspection — Decode and display the header, payload, and signature of any JWT token.
  • Expiration Check — Issued-at, not-before and expiry as dates in your time zone, with a live countdown: valid, expired, or not valid yet.
  • Claims Display — Every claim exactly as the token writes it — long numeric IDs keep all their digits, and repeated keys are flagged.
  • Fully Offline — Decoding happens in your browser. Your tokens are never sent to any server.

How It Works

  1. Paste your JWT — Paste a JSON Web Token in the input field.
  2. Inspect the decoded parts — View the header (algorithm, type), payload (claims, timestamps), and signature.
  3. Check expiration — See whether the token is still valid or has expired.

Use Cases

  • Debug authentication issues by inspecting JWT claims
  • Check when a token expires or becomes valid, and who issued it
  • Inspect tokens during API development and testing
  • Learn about JWT structure by examining real tokens

Frequently Asked Questions

Does this verify the JWT signature?

No. It decodes the token and shows what it claims; it doesn’t check the signature, and the page says so under every token. Verifying needs the issuer’s secret or public key and belongs on your server — never trust a token’s claims just because they decoded cleanly.

Is it safe to paste my JWT here?

The token is decoded by JavaScript in this tab and isn’t sent anywhere or saved — open the Network tab and watch it stay quiet while you paste. Still, a live token works like a password: paste test or expired tokens where you can.

What JWT formats are supported?

Signed JWTs (JWS) in the usual three-part header.payload.signature form, including unsigned alg "none" tokens. You can paste a whole "Authorization: Bearer …" line, a quoted string or a token wrapped across lines — the extras are removed and named. Encrypted tokens (JWE, five parts) can’t be read without the recipient’s key; the page tells you when you’ve pasted one.

Why does it show 12345678901234567890 when another decoder shows 12345678901234567000?

Because that’s what the token says. JavaScript numbers hold about 16 digits, so decoders that parse the JSON and print it again quietly change long IDs, turn 1.10 into 1.1 and drop a repeated key. This one shows the token’s own text, re-indented and nothing else.

What do iat, nbf and exp mean?

Issued at, not before and expires: seconds since 1 January 1970 (UTC). The page shows them as dates in your time zone and counts down live. A value in milliseconds is flagged, because libraries would read it as a date thousands of years away.

Notes from Milo 🐨

2026-10-05

A token with a long numeric user ID showed me a different ID than the one in the token: the decoder parsed the JSON and printed it back, and JavaScript quietly rounded 12345678901234567890 to 12345678901234567000. Now you see the token's own text, digit for digit, and repeated keys are flagged. While I was in there: you can paste a whole "Authorization: Bearer …" line or a token wrapped across lines, errors say which part is broken, a token that isn't valid yet (nbf) no longer says "valid for another 2h", the countdown is live, a few odd tokens no longer blank the whole page, and it fits a phone. One more thing it now says out loud under every token: decoded isn't verified.

From the blog

Related Tools

💬 Bug, idea, or just to say hi? Tell Milo 🐨 · [email protected]