LocalBench

What Is a JWT, and How Do You Read One Without a Server?

Published September 19, 2026

If you've worked with any modern web API, you've probably seen a long string like eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.4pcPyMD09olPSyXnrXCjTwXyr... show up in anAuthorization: Bearer header. That's a JSON Web Token, or JWT (pronounced "jot") — and despite looking like gibberish, it's just three pieces of plain JSON, encoded and glued together with dots.

The three parts of a JWT

Split a JWT on its two dots and you get three sections: header.payload.signature. The header and payload are each just a JSON object that's been Base64URL-encoded (a URL-safe variant of Base64 — see our Base64 guide if that part's unfamiliar). The signature is different: it's cryptographic proof that the header and payload haven't been tampered with since the token was issued.

  • Header — usually just the signing algorithm and token type, e.g. {"alg":"HS256","typ":"JWT"}.
  • Payload — the actual claims: who the token is for (sub), when it expires (exp), when it was issued (iat), and whatever custom data the issuer decided to include (a user ID, roles, a tenant ID, and so on).
  • Signature — computed by signing the header and payload together with a secret (HMAC algorithms like HS256) or a private key (RSA/ECDSA algorithms like RS256/ES256).

Decoding vs. verifying — these are not the same thing

This is the single most common misunderstanding about JWTs. Decoding a JWT just means reversing the Base64URL encoding on the header and payload to read the JSON underneath — anyone can do this with no secret or key at all, because Base64 is an encoding, not encryption. Paste any JWT into a decoder and you can read its claims in plain text.

Verifying a JWT is a completely different operation: it means recomputing the signature using the secret or public key and checking it matches the signature attached to the token. Only verification proves the token wasn't forged or altered. A payload you can read without a key is expected and by design — never put anything secret (a password, a raw credit card number) inside a JWT payload, since anyone who intercepts the token can read it without ever verifying it.

Why servers use JWTs instead of session IDs

A traditional session ID is a random string that's meaningless on its own — the server has to look it up in a database or cache on every request to find out who it belongs to. A JWT carries its own claims, so a server (or a different microservice entirely) can verify the signature and immediately know who the user is and whether the token is still valid, with no database round trip. That's what makes JWTs attractive for distributed systems and stateless APIs — the tradeoff is that a JWT can't be revoked early the way a server-side session can, short of maintaining a blocklist, so short expiration times (exp) matter more than they would with sessions.

Common pitfalls

  • Trusting the payload without verifying the signature. Some libraries let you "decode" without a verify step — never make an authorization decision based on decoded-but-unverified claims.
  • Accepting the alg from the token's own header. A known attack sends a token with "alg":"none" or swaps an asymmetric algorithm for a symmetric one; a correct verifier pins the expected algorithm itself rather than trusting whatever the token claims.
  • No expiration, or an expiration too far in the future. Since a JWT generally can't be revoked, a long-lived token that leaks stays valid for its entire lifetime.

Try it yourself

Paste any JWT into our JWT Debugger to see the header and payload decoded instantly, flagged for expiration, and — if you have the secret or public key — verified against its signature. Everything happens locally in your browser; a secret or private key you paste in is never sent anywhere. To build a test token from scratch, use the JWT Generator — pick an algorithm, fill in claims, and sign it.

← Back to all guides