How to Decode a JWT Token Safely (What's Inside It)
A JWT is decoded, not decrypted, because its three parts are Base64URL-encoded rather than encrypted, meaning anyone holding the token can read its contents without any secret or key. A JSON Web Token is simply three strings joined by dots, header.payload.signature, where the header and payload are plain JSON that has been Base64URL-encoded. This guide shows you exactly what is inside a JWT, how to read the standard claims, and the critical difference between decoding a token (which needs nothing) and verifying it (which needs the signing key).
What a JWT contains: header, payload, signature
A JWT contains three dot-separated segments, each Base64URL-encoded: a header, a payload, and a signature. Split a token on its two dots and you get exactly these three parts, and the first two decode straight back into readable JSON.
The header is a small JSON object naming the token type and the signing algorithm, for example `{"alg":"HS256","typ":"JWT"}`. The payload is the JSON object carrying the claims, the statements about the user or session such as their ID and the token's expiry. The signature is a cryptographic hash of the first two segments plus a secret key, and unlike the others it does not decode into readable text.
Because the first two parts are only Base64URL-encoded, decoding a JWT is trivial: reverse the encoding on the header and payload and you see the raw JSON. This is by design, JWTs are meant to be read by the systems that receive them.
Decoding vs verifying: the critical difference
Decoding a JWT requires no secret, but verifying one requires the signing key, and confusing the two is a serious security error. Decoding just reverses Base64URL to reveal the claims; verifying recomputes the signature with the secret key to prove the token is authentic and unaltered.
This means you can read any JWT you find, but reading it tells you nothing about whether to trust it. An attacker can take a valid token, decode it, change the payload to claim they are an administrator, and re-encode it. The forged token decodes perfectly; it just fails signature verification, because the attacker does not have the key needed to produce a matching signature.
The rule for servers: never make a trust decision based on a decoded payload alone. Always verify the signature against your key, and check the expiry, before acting on any claim. Decoding is for inspection and debugging; verification is for authorization.
Why JWTs are encoded, not encrypted
A standard signed JWT is encoded, not encrypted, so its payload is fully readable by anyone who obtains the token, which is why you must never place secrets inside it. The signature guarantees integrity, that the contents were not tampered with, but it provides no confidentiality; the claims sit in plain, decodable JSON.
Developers routinely make the mistake of putting sensitive data, passwords, full personal records, internal identifiers, into a JWT payload, assuming the token is opaque. It is not. Anyone who intercepts the token, from browser storage, a log file, or a network capture, can decode the payload in seconds.
Keep payloads to non-sensitive claims: a user ID, roles, and timing fields. If you truly need to hide the contents, that is a different construct, a JWE (JSON Web Encryption), which actually encrypts the payload. A plain signed JWT never does.
Reading the standard JWT claims
The JWT standard, RFC 7519, defines seven registered claim names that carry consistent meaning across systems, and all of them are optional but widely used. Recognizing them lets you read any token's payload at a glance, regardless of who issued it.
Three of these claims are timestamps, exp, iat, and nbf, and they are stored as Unix time: the number of seconds elapsed since January 1, 1970 UTC. A value like 1767225600 is not a random number; it is a date, and converting it reveals exactly when a token was issued or when it expires. To find a token's lifetime, subtract iat from exp.
The table below lists all seven registered claims and what each one means.
| Claim | Name | Meaning |
|---|---|---|
| exp | Expiration Time | Unix timestamp after which the token must be rejected |
| iat | Issued At | Unix timestamp of when the token was created |
| nbf | Not Before | Unix timestamp before which the token must not be accepted |
| iss | Issuer | Who issued the token, often a URL or service name |
| sub | Subject | Who the token is about, usually a user ID |
| aud | Audience | Intended recipient(s); your API should confirm it is listed |
| jti | JWT ID | A unique identifier for this specific token |
Can I decode a JWT without sending it to a server?
Yes, a client-side JWT decoder splits and Base64URL-decodes the token entirely in your browser, so the token is never transmitted to any server. Decoding is pure string manipulation that runs on your own device, no network request is needed to reveal the header and payload.
This is not just convenient, it is a real security control. A JWT is a bearer credential: whoever holds it can act as the user until it expires. Pasting a production token into a random online decoder sends that live credential to an unknown third party, who could capture and replay it. A tool that decodes locally eliminates that exposure entirely, letting you inspect real tokens without ever handing them to someone else's server.
Frequently asked questions
Can I decode a JWT without the secret key?
Yes. The header and payload are only Base64URL-encoded, so anyone can decode and read them without any key. The secret is required only to verify or create the signature, not to read the claims.
Is a JWT encrypted?
A standard signed JWT is not encrypted, only encoded and signed. The payload is readable by anyone who has the token. Use JWE if you actually need the contents encrypted.
What is the difference between decoding and verifying a JWT?
Decoding reveals the claims and needs no secret. Verifying recomputes the signature with the signing key to confirm the token is authentic and unchanged. Only verified tokens should be trusted.
What do exp and iat mean in a JWT?
They are the expiration and issued-at times, stored as Unix timestamps (seconds since 1970). Subtract iat from exp to get the token's lifetime; a token is expired once the current time passes exp.
Is it safe to paste a JWT into an online decoder?
Only if the decoder runs entirely in your browser. A JWT is a live bearer credential, and pasting a production token into a server-side decoder sends it to a third party who could replay it. Use a client-side tool.