How to decode a JWT (with and without code)
A JWT's header and payload are just base64url-encoded JSON — no key or secret is needed to read them. Split the token on dots, decode the first two parts, done. The only subtlety is that it's base64url (RFC 4648 §5): - and _ instead of + and /, with padding stripped.
The rule that matters: decoding proves nothing. Anyone can mint a token claiming to be anyone; only verifying the signature with a key makes claims trustworthy. Never make an authorization decision from decoded-but-unverified claims — that's the root of several real JWT attacks.
Online, without sending the token anywhere
Paste the token into the TokenPrism debugger. Decoding happens entirely in your browser — verifiably: no network request is made — and every known claim is annotated, timestamps like exp are translated, and an RFC 8725 linter flags weak patterns.
JavaScript
function decodeJwtPayload(token) {
const part = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')
return JSON.parse(atob(part))
}
In Node.js, Buffer.from(part, 'base64url').toString() handles base64url directly. For production code prefer a maintained library (jose, jwt-decode) — and remember neither call above checks the signature.
Python
import base64, json
def decode_jwt_payload(token):
part = token.split('.')[1]
padded = part + '=' * (-len(part) % 4)
return json.loads(base64.urlsafe_b64decode(padded))
With PyJWT, jwt.decode(token, options={"verify_signature": False}) does the same — the explicit opt-out exists precisely so you can't skip verification by accident.
Java
String part = token.split("\\.")[1];
String json = new String(Base64.getUrlDecoder().decode(part), StandardCharsets.UTF_8);
Go
part := strings.Split(token, ".")[1]
payload, err := base64.RawURLEncoding.DecodeString(part)
Common decode failures
- "Invalid character" / bad padding — you used a plain base64 decoder on base64url input, or forgot to re-pad in Python.
- Only 2 segments, or 5 — 2 means an unsecured (
alg:none) token; 5 means it's an encrypted JWE, whose payload can't be read without the key. - Absurd expiry dates — a producer wrote milliseconds into
exp; it's defined in epoch seconds.