JWT Decoder

Paste a JWT to read its header and claims, with exp, nbf and iat converted to dates. Optionally verify the signature with a secret or public key. Nothing leaves your browser.

Processed locally in your browser
Decodes locally · signature is only checked if you supply a key
Token
The three segments appear here, colour-coded.
Header
Header
Payload
Payload (claims)
Waiting for a tokenNothing is sent anywhere

Claims

Registered claims (exp, iat, nbf…) are explained and timestamps converted once a token is decoded.

What a JWT is

A JSON Web Token (RFC 7519) is three Base64url-encoded segments separated by dots: a header that names the signing algorithm, a payload of claims, and a signature over the first two. The header and payload are not encrypted, only encoded. Anyone holding a token can read its contents, which is exactly what this tool does.

Header
{"alg": "HS256", "typ": "JWT"}
Payload
{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}

Decoding is not verification

Decoding shows what the token says. It does not tell you whether the token was issued by the party it claims, or whether it has been modified. That requires checking the signature with the issuer's key: a shared secret for HMAC algorithms (HS256), or the issuer's public key for RSA and ECDSA algorithms (RS256, ES256). This tool only reports “Signature valid” after actually running that check with a key you provide. Without one it says, plainly, that the signature has not been verified.

Two rules for server-side code follow from this. Never trust claims from a token you have not verified. And never let the token choose the algorithm: reject alg: none and pin the algorithms you expect, otherwise an attacker can downgrade an RSA-signed token to an HMAC one “signed” with your public key.

Registered claims

ClaimMeaningNotes
issIssuerWho created the token. Verify it matches the expected authority.
subSubjectThe principal the token is about, usually a user ID.
audAudienceWho the token is for. A string or an array. Reject tokens not addressed to your service.
expExpiration timeUnix seconds. The token is invalid at or after this time.
nbfNot beforeUnix seconds. The token is invalid before this time.
iatIssued atUnix seconds. Useful for detecting tokens that are too old even if not yet expired.
jtiJWT IDUnique identifier, used to reject replays.

Timestamps are in seconds, not milliseconds. A 13-digit value is a bug in the issuer. The claims table above converts each timestamp to UTC and to your local time and says how far in the past or future it is. The Unix Timestamp Converter does the same for arbitrary values.

Common problems

  • “Expected three segments.” The token was truncated, has whitespace in it, or is a JWE (five segments, encrypted). A Bearer prefix is stripped automatically.
  • Header or payload will not decode. The segment is not Base64url, or it decodes to something that is not JSON. Opaque tokens from some providers look like JWTs but are not.
  • Expired. Check the server clock too: a few seconds of skew is normal, and most libraries accept a small leeway.
  • Signature does not match with the right secret. Some frameworks store the HMAC secret Base64-encoded and decode it before signing. Tick the Base64 option and try again.

Verifying in code

Node.js (jose)

import { jwtVerify, createRemoteJWKSet } from "jose";
const JWKS = createRemoteJWKSet(new URL("https://issuer.example.com/.well-known/jwks.json"));
const { payload } = await jwtVerify(token, JWKS, {
  issuer: "https://issuer.example.com",
  audience: "my-api",
  algorithms: ["RS256"],
});

Python (PyJWT)

import jwt
payload = jwt.decode(token, key, algorithms=["HS256"], audience="my-api")
# Decode without verifying, for debugging only:
jwt.decode(token, options={"verify_signature": False})

Privacy

Decoding uses a local Base64url decoder and JSON.parse; verification uses crypto.subtle. No part of the token, secret or key leaves your browser. Tokens are credentials: treat any browser tab where you paste one as you would a terminal, and prefer expired or test tokens when you can.

navigateEnter openEsc close