JWT Decoder Guide: Parse & Verify JSON Web Tokens
JWT Decoder Guide: Parse & Verify JSON Web Tokens
A JWT (JSON Web Token) is the compact credential you receive after logging in to most modern web and mobile apps. It looks like a random string of letters, dots, and dashes — but it is actually three small JSON objects glued together. When an API hands you a token and you need to know what it says, a JWT decoder takes that opaque blob and shows you the readable claims inside. Paste one into our JWT Decoder and it parses in your browser — the token never leaves your machine.
This guide explains what a JWT decoder does, the three segments of a token, how base64url encoding works, the traps that trip up almost everyone, and when to use a tool instead of writing code.
What Is a JWT Decoder?
A JWT decoder is a tool that splits a token on its two . separators and
decodes each segment back into plain text. Because a JWT is not encrypted — it is
only encoded — decoding does not require a password or a private key. Anyone
who holds the token can read its contents.
The decoder performs three steps:
- Split the string at the two dots into header, payload, and signature.
- Base64url-decode the header and payload (both are JSON).
- Pretty-print the resulting JSON so you can read the claims.
Important: decoding is not the same as verifying. A decoder shows you what a token says; it does not prove the token is authentic. Verification needs the server's secret or public key.
The Three Parts of a JWT
Every JWT has the shape header.payload.signature.
| Part | Encoded as | What it contains |
|---|---|---|
| Header | base64url JSON | The signing algorithm (alg) and token type (typ) |
| Payload | base64url JSON | The claims — subject, expiry, issuer, custom data |
| Signature | base64url of bytes | Proof that the first two parts were not tampered with |
A real example:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
After decoding, the payload reads {"sub":"1234567890","name":"Alice"}. Notice
there is nothing secret here — anyone can decode it the same way.
Why Decode a JWT?
You typically reach for a decoder in a few situations:
- Debugging auth — your frontend keeps getting 401s; you decode the token to
see whether the
expalready passed or thesubis what you expect. - Inspecting claims — confirming the
role,email, orscopea backend actually issued, instead of guessing from behavior. - Checking expiry — the
expfield is a Unix timestamp; a decoder shows the human-readable date so you can tell if a session is stale. - Learning — understanding how libraries like
jsonwebtokenorPyJWTinterpret the bytes under the hood.
How a Decoder Works
Under the hood the process is simple:
- Locate the first
.and the last.to isolate the three segments. - Replace base64url characters (
-→+,_→/) and re-add padding. - Decode the bytes as UTF-8 text.
- Parse the text as JSON and format it.
The signature segment is not JSON. It is the raw output of a MAC or digital
signature over header.payload, so a decoder shows it as a byte string, not an
object. To actually check it, you need the signing secret or public key — that is
verification, not decoding.
Base64url vs Base64
JWTs use base64url, a URL-safe variant of standard Base64. The difference matters when you decode by hand:
| Feature | Base64 | Base64url (JWT) |
|---|---|---|
+ character | used | replaced with - |
/ character | used | replaced with _ |
Padding = | required | stripped off |
If you feed a JWT segment into a standard Base64 decoder, the - and _
characters will fail. A JWT decoder handles the translation automatically — which
is exactly why reaching for the tool beats a quick atob() one-liner.
Common Pitfalls
These are the mistakes a decoder (and its users) hit most often:
- Decoding instead of verifying — reading the payload does not mean the token is valid. An attacker can forge any payload; only signature verification proves authenticity.
- Trusting
alg: none— some libraries accept tokens with no signature if the header saysalg: none. Always reject unsigned tokens on the server. - Algorithm confusion — an RS256 (asymmetric) key can be abused if the server is tricked into verifying it as HS256 (symmetric) with the public key. Pin the expected algorithm.
- Misreading
exp— the expiry is in seconds since the Unix epoch, not milliseconds like JavaScript'sDate.now(). Off by 1000× is a classic bug. - Leaking secrets in the payload — because JWTs are only encoded, never put passwords, tokens, or PII in claims. Anyone who sees the token sees the data.
Code Examples
JavaScript
// Decode (NOT verify) a JWT in the browser
function decodeJwt(token) {
const [header, payload] = token.split(".");
const toJson = (b64) =>
JSON.parse(atob(b64.replace(/-/g, "+").replace(/_/g, "/")));
return { header: toJson(header), payload: toJson(payload) };
}
const tok =
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U";
console.log(decodeJwt(tok));
// → { header: { alg: 'HS256', typ: 'JWT' }, payload: { sub: '1234567890' } }
// Check expiry (exp is in SECONDS)
const exp = decodeJwt(tok).payload.exp;
console.log(new Date(exp * 1000).toISOString());
Python
import base64, json
def decode_jwt(token: str) -> dict:
header_b64, payload_b64, _ = token.split(".")
# re-add padding for standard base64
def b64url_to_json(seg: str) -> dict:
seg += "=" * (-len(seg) % 4)
return json.loads(base64.urlsafe_b64decode(seg))
return {"header": b64url_to_json(header_b64),
"payload": b64url_to_json(payload_b64)}
tok = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U"
print(decode_jwt(tok))
# → {'header': {'alg': 'HS256', 'typ': 'JWT'}, 'payload': {'sub': '1234567890'}}
Both snippets decode only — neither proves the token is trustworthy. Use a
verification library (such as jsonwebtoken or PyJWT) with the correct key for
that step.
Related Tools
- Decode any token instantly with the JWT Decoder.
- Understand the base64url layer with the Base64 Encoder / Decoder.
- Generate HMAC signatures for your own tokens with the HMAC Generator.
- Pretty-print the JSON payload with the JSON Formatter.
- Build alternative HTTP credentials with the Basic Auth Generator.
When to Use a Decoder Instead of Code
You can split a token with one line of atob() or base64.urlsafe_b64decode,
so why open a tool? The same reason you reach for a
JSON Formatter: when a token shows up in a log, a response
header, or a chat message and you want to read it now. The tool handles the
base64url translation, pretty-prints the JSON, and keeps the token on your
machine — no npm install, no pasting secrets into a cloud service. For
production code, keep a proper verification library in your app; for ad-hoc
inspection and debugging, the decoder is faster and safer.