Decode a JWT — in the browser and in a shell one-liner.
Every JWT is three base64url-encoded strings separated by dots. The first two are JSON — you don't need a library to read them. This guide covers the browser flow (with signature verification), a shell one-liner for scripts, and when to sign your own.
Anatomy
A JWT looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0In0.abc123
Three parts, dot-separated:
- Header — base64url-encoded JSON. Tells you the signing algorithm.
- Payload — base64url-encoded JSON. Your claims:
sub,exp,iat, and whatever else the issuer put in. - Signature — HMAC or asymmetric signature over the first two parts.
Browser flow
- Open /jwt/. Paste the token into the input.
- Instant decode. Header and payload appear as pretty-printed JSON, color-coded. Registered claims (
exp,iat,nbf) are annotated with their human meaning and expiry warnings. - Verify signature (optional). Paste the secret (for HS-family) or public key (for RS/ES) and the tool computes the signature and compares. Green if valid.
Shell one-liner
For scripts and CI, decode without leaving the terminal. Base64url isn't standard base64 — the padding is stripped and / becomes _, + becomes -. Restore before decoding:
echo "eyJzdWIiOiIxMjM0In0" | tr '_-' '/+' | base64 -d 2>/dev/null | jq
For a full JWT, extract the payload (second dot-separated part) first:
TOKEN="eyJhbGc...abc"
echo "$TOKEN" | cut -d. -f2 | tr '_-' '/+' | base64 -d 2>/dev/null | jq
Header is the same but cut -d. -f1. Signature (part 3) is not JSON — it's a raw byte hash.
Signing your own
Sometimes you need to issue a JWT, not just decode one — for local testing, a mock auth server, or a quick script. /jwt-signer/ ships HS256/HS384/HS512 signing in the browser with crypto.subtle. Your secret never leaves the browser.
Common gotchas
- Expiry:
expis a Unix timestamp in seconds, not milliseconds. Off-by-1000 is a classic bug. - Timezone: JWT timestamps are always UTC. Comparing to your local time will drift.
- Base64url ≠ base64: standard base64
-doften fails on JWTs. Do thetrreplacement first. - None algorithm: never trust
alg: none. Always verify the signature.