Understanding JWT structure and how to inspect or decode tokens for debugging and learning
If you've worked with APIs, OAuth, or single sign-on (SSO), you've probably encountered JWT—JSON Web Tokens. JWTs are a standard way to transmit information between parties as a compact, URL-safe string. They're used for authentication ("who is this user?") and to pass claims. But what's inside a JWT, and how do you decode it? This guide explains the structure and how to decode JWT online for free.
JWT stands for JSON Web Token. It's a string made of three parts separated by dots: header.payload.signature. Each part is Base64url-encoded JSON. Unlike session cookies stored on the server, JWTs are self-contained: the token itself holds the data. The server signs it with a secret, so anyone with the secret can verify it wasn't tampered with.
Describes the token type and algorithm. Example: {"alg":"HS256","typ":"JWT"}. The algorithm (e.g., HS256, RS256) tells verifiers how the signature was created.
Contains the "claims"—data about the user or session. Common claims include sub (subject/user ID), exp (expiration), iat (issued at), and custom claims like email or role. The payload is Base64-encoded, not encrypted—anyone can decode it and read the contents.
The signature verifies the token wasn't modified. The server combines header + payload with a secret key, hashes it, and appends the result. Without the secret, you can't create a valid signature, but you can decode and view the header and payload.
Decoding a JWT means Base64-decoding the header and payload. The signature can't be verified without the secret, but you can read the contents. A JWT decoder takes your token string, splits it by dots, decodes each part, and displays the JSON. No signup needed—paste the token and see the result.
The payload is Base64-encoded, not encrypted. Anyone can decode it. Never put passwords, API keys, or sensitive data in the payload. Use it for non-sensitive claims (user ID, roles, expiration). For sensitive data, use encryption (e.g., JWE) in addition to JWT.
{
"sub": "user-12345",
"email": "user@example.com",
"iat": 1704067200,
"exp": 1704153600
}
After decoding, you might see a user ID (sub), email, issue time (iat), and expiration (exp). Use a decoder to inspect any JWT you're working with.