CodeToolProCodeToolPro
GitHub
Encoders / Decoders·6 min read

JWT Decoder Guide: Parse & Verify JSON Web Tokens

CodeToolPro Team·

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:

  1. Split the string at the two dots into header, payload, and signature.
  2. Base64url-decode the header and payload (both are JSON).
  3. 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.

PartEncoded asWhat it contains
Headerbase64url JSONThe signing algorithm (alg) and token type (typ)
Payloadbase64url JSONThe claims — subject, expiry, issuer, custom data
Signaturebase64url of bytesProof 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 exp already passed or the sub is what you expect.
  • Inspecting claims — confirming the role, email, or scope a backend actually issued, instead of guessing from behavior.
  • Checking expiry — the exp field 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 jsonwebtoken or PyJWT interpret the bytes under the hood.

How a Decoder Works

Under the hood the process is simple:

  1. Locate the first . and the last . to isolate the three segments.
  2. Replace base64url characters (-+, _/) and re-add padding.
  3. Decode the bytes as UTF-8 text.
  4. 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:

FeatureBase64Base64url (JWT)
+ characterusedreplaced with -
/ characterusedreplaced with _
Padding =requiredstripped 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 says alg: 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's Date.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

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.