Skip to content
ToolsNow
Guides All tools

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:

ClaimNameMeaning
ississuerWho created the token
subsubjectWho the token is about — usually the user ID
audaudienceWho it is intended for
expexpirationWhen it stops being valid
iatissued atWhen it was created
nbfnot beforeWhen it starts being valid
jtiJWT IDUnique 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.

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:

  1. exp in the past? Overwhelmingly the most common cause. Check iat as well, because an implausible issue time means clock skew between servers.
  2. aud mismatch? Tokens minted for one API get rejected by another.
  3. Wrong alg? A verifier expecting RS256 will reject HS256 tokens.
  4. 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.