What is a JWT, and how do you decode one safely?
· 6 min read
If you've ever inspected an API request and seen a long string starting with eyJ..., you've met a JWT — a JSON Web Token. They're everywhere in modern authentication, and yet they're widely misunderstood. This guide explains what a JWT actually is, what its three parts mean, how verification works, and — importantly — why you should never paste a real token into a random website to "just decode it."
What a JWT is
A JWT is a compact, URL-safe way to represent claims — small facts like "this is user 42," "they're an admin," and "this token expires at 3pm." A server issues the token when you log in; your client sends it back on each request; the server trusts it because it can check the token wasn't tampered with. No database lookup required, which is why JWTs scale well.
The critical thing to understand: a standard JWT is signed, not encrypted. The contents are merely Base64URL-encoded, not hidden. Anyone holding the token can read what's inside it. The signature doesn't hide the data — it proves the data wasn't changed.
The three parts
A JWT is three Base64URL chunks separated by dots: header.payload.signature.
1. Header
A little JSON object saying what kind of token this is and which algorithm signed it, e.g. { "alg": "HS256", "typ": "JWT" }. The alg matters a lot for verification.
2. Payload
The claims themselves — the actual data. You'll often see registered claims like sub (subject/user), exp (expiry, as a Unix timestamp), iat (issued-at), and iss (issuer), plus any custom fields the app added. Because it's only encoded, this is readable by anyone — so never put secrets or passwords in a payload.
3. Signature
A cryptographic signature over the header and payload. With a symmetric algorithm like HS256, it's an HMAC computed with a shared secret. With an asymmetric one like RS256, it's signed with a private key and verified with the matching public key. If even one character of the header or payload changes, the signature no longer matches.
What "verifying" a JWT means
Decoding and verifying are two different things. Decoding just Base64-decodes the header and payload so you can read them — no secret needed, and it proves nothing. Verifying recomputes the signature with the secret or public key and checks it matches, then confirms the token hasn't expired. Only a verified token should ever be trusted.
A common security mistake is trusting a decoded payload without checking the signature — or accepting a token whose alg was switched to none. Always verify on the server before you believe a single claim.
Why not to paste tokens into random websites
Here's the uncomfortable part. A live JWT is often a bearer credential: whoever holds it can act as you until it expires. Plenty of "JWT decoder" sites send the token you paste to their backend. If that token is still valid, you've just handed a third party the keys to your session or API — and if you paste the signing secret to verify it, that's even worse.
The safe approach is to decode and verify locally, in your own browser, so the token never travels anywhere. That's exactly what KeepItLocally's JWT Decoder does: it's a static site with no backend, decodes the header and payload on your device, and can verify an HS256 signature with a secret you type — none of which is ever transmitted. Open DevTools → Network and you'll see nothing leave the page.
Quick reference
- Signed, not encrypted — the payload is readable; never store secrets in it.
expis a Unix timestamp — decode it with a timestamp converter to read the expiry.- Verify before trusting — a decoded payload alone proves nothing.
- Keep live tokens off strangers' servers — decode locally.