How to read a JWT (and what the three parts actually do)
A JSON Web Token is three Base64 sections split by dots — readable by anyone, forgeable by no one. How the format works, the claims, and the classic pitfalls.
Published
Open your browser’s developer tools on almost any logged-in web app and you will find a JWT: a long string of letters, digits and exactly two dots. That token is probably what keeps you logged in — and despite appearances, most of it is readable by anyone who holds it.
The shape: three parts, two dots
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjM0In0 . SflKxwRJSMeKKF2QT4fwpM...
header payload signature
Each section is Base64url-encoded (a URL-safe Base64 variant using - and
_ instead of + and /, with padding dropped). The first two decode to
plain JSON. The third is binary — a signature — and does not decode to
anything readable, which is correct and expected.
The header says how the token is signed:
{ "alg": "HS256", "typ": "JWT" }
The payload carries the claims — the actual content:
{
"sub": "user-1234",
"name": "Jane Doe",
"iat": 1753487000,
"exp": 1753490600
}
The signature is computed over the first two sections with a secret (or private key). It is what makes the token trustworthy.
Paste any JWT into the decoder here and both JSON sections appear instantly — it runs locally, which matters, because a real token pasted into a random website is a credential handed to a stranger.
Reading the standard claims
The registered claim names are terse by design (the spec wanted small tokens):
| Claim | Name | Meaning |
|---|---|---|
iss | issuer | Who created the token |
sub | subject | Who the token is about — usually the user ID |
aud | audience | Who it is intended for |
exp | expiration | When it stops being valid |
iat | issued at | When it was created |
nbf | not before | When it starts being valid |
jti | JWT ID | Unique token identifier |
The timestamps are Unix time — seconds since 1 January 1970 UTC. So
"exp": 1753490600 is a moment, not a duration; a decoder worth using
translates it to a date and tells you whether it has passed. Anything else
in the payload (name, role, email…) is a custom claim the issuing
application chose to include.
What the signature does and does not do
The signature is the entire security story, and its guarantee is precise: the token was created by someone holding the key, and has not been altered since. Change one character of the payload and the signature no longer matches; without the key, a matching signature cannot be produced.
What the signature does not do is hide anything. The payload is encoded, not encrypted — this trips up developers constantly, and it means: no secrets in JWT payloads, ever. Anyone who obtains the token (browser storage, logs, a shared link) reads every claim. The related distinction between encoding, encryption and hashing is its own article.
Two signing families are common: HS256 (one shared secret both signs
and verifies) and RS256/ES256 (a private key signs, a public key
verifies — anyone can check validity, only the issuer can mint). Which is
in use is right there in the header’s alg field.
Why this design is popular: stateless sessions
Traditional sessions store state on the server; the browser holds only a session ID. JWTs invert this: the server signs a token containing the session data and holds nothing. Any server with the verification key can validate a request without a database lookup — which is why JWTs dominate in APIs, microservices and single sign-on.
The inversion has a famous cost: a JWT cannot be revoked. It is valid
until exp, whoever holds it, because there is no server-side record to
delete. This is why real systems issue short-lived access tokens (minutes)
paired with longer-lived refresh tokens, and why “log out everywhere”
features are harder to build than they sound.
Debugging checklist
When a token is rejected, the decoded contents usually explain it:
expin the past? The overwhelmingly common cause. Checkiattoo — an implausible issue time means clock skew between servers.audmismatch? Tokens for one API get rejected by another.- Wrong
alg? A verifier expecting RS256 rejects HS256 tokens. - Not three dot-separated parts? It is not a JWT at all — opaque session tokens and API keys look similar and decode to nothing.
None of these require the signing key to diagnose — which is the practical upside of a format where the envelope is transparent and only the seal is secret.