If you've debugged an API integration, inspected a login request in devtools, or worked with OAuth, you've seen a JWT — a long string starting with "eyJ" and split into three dot-separated segments. Here's what's actually in it.
The three parts of a JWT
A JWT (JSON Web Token) is three Base64URL-encoded segments joined by dots: header.payload.signature.
- Header — metadata about the token, typically the signing algorithm (e.g. HS256 or RS256) and token type
- Payload — the actual claims: user ID, expiration time (exp), issued-at time (iat), roles, or any custom data the issuer chose to include
- Signature — a cryptographic signature over the header and payload, generated with a secret or private key, used to verify the token hasn't been tampered with
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cThe part everyone gets wrong: decoding vs. verifying
This is the single most important thing to understand about JWTs: the header and payload are Base64-encoded, not encrypted. Anyone can decode them — paste a token into a decoder and you'll instantly see the claims in plain JSON. That's by design; JWTs are meant to be readable by any party that receives them.
What you can't do without the secret key is verify that the token is authentic and hasn't been altered. That's what the signature is for. A decoder shows you the claims; only the server holding the signing secret (or public key, for RS256) can confirm the signature is valid. Never trust a JWT's contents as authoritative without verifying the signature server-side — decoding alone tells you what a token claims, not whether it's genuine.
Common things you'll check when decoding
- exp — has the token expired? (Unix timestamp, compare against current time)
- iat / nbf — when was it issued, and is there a "not before" restriction?
- sub — the subject, usually the user or account ID
- aud / iss — the intended audience and issuer, useful for spotting misconfigured tokens across environments
- alg in the header — if it says "none," that's a red flag; some libraries historically had vulnerabilities around accepting unsigned tokens
A quick word on security
Because a JWT's payload is plainly readable, never put secrets, passwords, or sensitive personal data directly in the claims — anyone who intercepts the token (or just opens devtools) can read them. Treat the payload like a signed but public postcard, not a locked box.
This decoder runs entirely client-side — your token is parsed in the browser and never sent anywhere, which matters since tokens are often tied to live sessions.