%url-decoder.net

How to Read a JWT (and Why You Should Not Trust It Blindly)

Updated July 5, 2026 · 4 min read

A JSON Web Token looks like line noise: three runs of letters and digits separated by dots. It is actually one of the most readable formats in web development, and that readability is both its convenience and its most misunderstood property. Here is how to read one, and where reading stops being trusting.

The anatomy

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiJ1c3JfODIifQ . sig...
header                                payload              signature

Each of the first two parts is a JSON object encoded with base64url, the URL-safe Base64 variant. That is encoding, not encryption: anyone who holds the token can decode it in a millisecond. The header says how the token is signed, typically an alg like HS256 or RS256 and a typ of JWT. The payload carries the claims. The signature is raw bytes computed over the first two parts with the issuer's key.

Reading the claims

Claims are just JSON fields, and seven of them are registered with standard meanings: iss says who issued the token, sub whom it is about, aud which service it is for, and jti gives it a unique ID. The three time claims cause the most confusion because they are Unix timestamps, seconds since January 1, 1970: iat is when the token was issued, nbf is the moment it becomes valid, and exp is the moment it stops being accepted. A timestamp like 1751500000 tells a human nothing, which is why a decoder that converts them to local time and says "expires in two hours" saves real debugging time.

The debugging checklist

  • 401 with a fresh-looking token: decode it and check exp first. Expiry windows are shorter than people expect, often minutes.
  • Token rejected the instant it is issued: compare nbf and iat to your server clock. A few seconds of clock skew between machines is enough; that is why validators accept a small leeway.
  • Valid token, wrong service: check aud. Tokens issued for one API are routinely replayed against another and correctly refused.
  • Roles or flags missing: look at what the payload actually contains rather than what the login flow was supposed to put there.

Where trust has to stop

Everything you just read, an attacker can also read, and more importantly, write. A forged token can claim any sub and any role; what stops it is signature verification, which requires the issuer's secret or public key and belongs on the server, in a maintained JWT library. Two rules follow directly. First, never put secrets in a payload, because a JWT is readable by design; confidentiality requires the encrypted JWE variant instead. Second, never accept a token whose header says "alg": "none", a historical footgun that declares the token unsigned.

Treat the token itself like a password while you inspect it: a decoder that runs entirely in the browser exists precisely so that session tokens never land in some website's server logs.

Try everything in this guide hands-on, free and entirely in your browser.

Decode a token in the JWT Decoder

Keep reading