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 and forgeable by no one. How the format works, the claims, and the classic pitfalls.
By ToolsNow · Published
Open your browser’s developer tools on almost any logged-in web app and you’ll find a JWT: a long string of letters, digits and exactly two dots. That token is probably what’s keeping you logged in. Despite how it looks, most of it is readable by anyone holding it.
The shape: three parts, two dots
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjM0In0 . SflKxwRJSMeKKF2QT4fwpM...
header payload signature
Each section is Base64url-encoded, which is a URL-safe Base64 variant using
- and _ in place of + and /, with the padding dropped. The first
two decode to plain JSON. The third is binary, because it’s a signature, so
it won’t decode to anything readable. That’s correct and expected.
The header says how the token is signed:
{ "alg": "HS256", "typ": "JWT" }
The payload carries the claims, meaning 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 a private key. It’s what makes the token trustworthy.
Paste any JWT into the decoder here and both JSON sections appear straight away. It runs locally, which matters: 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, because 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, and a decoder worth using
translates it into a date and tells you whether it’s passed. Anything else
in the payload (name, role, email and so on) is a custom claim the
issuing application decided to include.
What the signature does and doesn’t do
The signature is the entire security story, and its guarantee is precise: the token was created by someone holding the key, and hasn’t been altered since. Change one character of the payload and the signature stops matching. Without the key, you can’t produce a signature that does match.
What it doesn’t do is hide anything. The payload is encoded, not encrypted. Developers trip over this constantly, and the practical consequence is simple: no secrets in JWT payloads, ever. Anyone who gets hold of the token (browser storage, logs, a shared link) can read every claim in it. The distinction between encoding, encryption and hashing gets its own article.
Two signing families dominate. HS256 uses one shared secret to both
sign and verify. RS256 and ES256 use a private key to sign and a
public key to verify, so anyone can check validity while only the issuer
can mint. Which one you’re looking at is right there in the header’s alg
field.
Why this design is popular: stateless sessions
Traditional sessions keep state on the server and hand the browser a session ID. JWTs invert that. The server signs a token containing the session data and then holds nothing at all, so any server with the verification key can validate a request without touching a database. That one property explains why JWTs dominate in APIs, microservices and single sign-on.
The inversion has a famous cost. A JWT can’t be revoked. It stays valid
until exp, whoever’s holding it, because there’s no server-side record to
delete. Hence short-lived access tokens measured in minutes, paired with
longer-lived refresh tokens, and hence “log out everywhere” being much
harder to build than it sounds.
Debugging checklist
When a token gets rejected, the decoded contents usually explain why:
expin the past? Overwhelmingly the most common cause. Checkiatas well, because an implausible issue time means clock skew between servers.audmismatch? Tokens minted for one API get rejected by another.- Wrong
alg? A verifier expecting RS256 will reject HS256 tokens. - Not three dot-separated parts? Then it isn’t a JWT at all. Opaque session tokens and API keys look similar and decode to nothing.
None of that needs the signing key to diagnose, which is the everyday upside of a format where the envelope is transparent and only the seal is secret.
Published by ToolsNow. Read how tools and sources are checked.
Found a mistake or an outdated detail? Send a correction with the article title and the detail to review.