JWT Decoder & Verifier
Decode and verify JSON Web Tokens (HS256, RS256, ES256) in your browser.
- Free
- No signup
- Files never leave your browser
What a JWT actually is
A JSON Web Token is three base64url-encoded chunks separated by dots:
header.payload.signature
- Header is a tiny JSON object that describes how the signature was made (algorithm, key id).
- Payload is a JSON object of claims — facts the issuer asserts about the subject, plus standard time fields.
- Signature is the cryptographic proof that the header and payload have not been tampered with since the issuer signed them.
The encoding is base64url, not base64 — + becomes -, / becomes _, and padding = is stripped. The decoder in this tool handles all three reversibly.
Decoding tells you what the token claims. Verifying tells you whether to believe those claims.
How the tool reads a token
- Split the input on
.into three parts. Fewer or more parts → error. - base64url-decode the header bytes; parse the result as JSON. Malformed JSON → error.
- base64url-decode the payload bytes; parse as JSON. Same error path.
- base64url-decode the signature bytes but do not interpret them — they are opaque binary until a key is supplied.
- Evaluate time claims:
iat,nbf,expare read as Unix seconds; the tool compares them to your device clock and surfaces “active”, “not yet valid”, or “expired”.
How verification works
You supply a key. The tool calls crypto.subtle.verify with the signature, the signing input (header.payload as raw text), and the key:
- HS256 / HS384 / HS512 — HMAC. The key is a plain text secret. WebCrypto imports it as a raw HMAC key with the matching SHA variant.
- RS256 / RS384 / RS512 — RSASSA-PKCS1-v1_5. The key is the issuer’s RSA public key, accepted as PEM (SPKI) or JWK (
kty: "RSA"). - ES256 / ES384 / ES512 — ECDSA on P-256, P-384, or P-521. The key is the issuer’s EC public key, accepted as PEM or JWK (
kty: "EC"). The tool handles both raw (JOSE) and DER-encoded signature formats. - PS256 / PS384 / PS512 — RSA-PSS with the matching SHA variant and standard salt length.
If WebCrypto returns true, the signature is mathematically valid for the given key. That alone does not mean the token is trustworthy — it only proves “whoever holds that key signed this”. You still need to trust the key.
When verification “succeeds” but you should still be careful
- The key might be wrong (you grabbed a development key, or a rotated one). Always verify against the issuer’s current public key, fetched over HTTPS from a trusted source like a JWKS endpoint.
- The
audclaim may not match the audience you expect. - The
issclaim may be untrusted. - The token may be expired even though the signature is valid.
This tool surfaces exp / nbf / iat as separate chips so you can spot stale tokens at a glance.
When to use the share link
Useful for asking a colleague “is this expired?” or “does this look right?” without copy-pasting raw token characters around. Useful for filing a bug report against a JWT-issuing service. Useful for sharing a decoded view in documentation.
The share link does not include the verification key. That is deliberate: the link can travel by email, chat, or paste without leaking a signing secret. The recipient sees the same decoded payload, but must supply their own key (or none) to verify.
Privacy and security
Identical posture to the rest of the multitool. A static HTML page, a small JavaScript bundle, no analytics on token content. WebCrypto runs in your browser tab. Open DevTools → Network and watch — no requests fire when you paste, decode, or verify.
Reminder: production tokens are credentials. Treat the act of pasting one anywhere — including this tool — the way you would treat pasting a password. If in doubt, generate a throwaway token for debugging.
Related tools
- Regex Tester — debug regular expressions live.
- JSON to CSV Converter — convert between JSON and CSV.
- QR Code Generator with Logo — generate branded QR codes.
Frequently asked questions
What does this tool actually do?
It splits a JWT into its three base64url parts, decodes the header and payload as JSON, evaluates the standard time claims (iat, nbf, exp), and optionally verifies the signature using a secret or public key you supply. The entire flow runs in your browser — no token data leaves your tab.
Is it safe to paste a production JWT here?
No. Treat real tokens as credentials. Even though this tool never sends your token to a server, the token is in your browser history and may be exposed via screen recordings, copy buffers, browser extensions, or shoulder-surfing. Use throwaway tokens for debugging, or revoke any production token you paste anywhere external.
Which signing algorithms are supported?
HS256, HS384, HS512 (HMAC with a text secret); RS256, RS384, RS512 (RSASSA-PKCS1-v1_5 with a PEM or JWK public key); ES256, ES384, ES512 (ECDSA with a PEM or JWK public key); and PS256/PS384/PS512 (RSA-PSS). All verification is done via the browser's WebCrypto API.
What is the "none" algorithm?
A JWT with alg:"none" carries no signature. The spec includes it but every modern library rejects it for authentication. This tool flags it explicitly: the payload is decoded, but the token is marked untrusted because anything can claim to be its issuer.
What is the difference between a JWK and a PEM?
Both are ways to encode a public key. PEM is the classic format with -----BEGIN PUBLIC KEY----- header and base64-encoded SPKI body. JWK (JSON Web Key) wraps the key as a JSON object with kty, n, e, x, y, etc. JWKS endpoints (used by Auth0, Cognito, Firebase, etc.) return JWK arrays. This tool accepts either.
What is "exp" / "nbf" / "iat" and how is the expiration checked?
"iat" is when the token was issued, "nbf" is the earliest time it is valid, and "exp" is when it expires — all in Unix seconds. The tool checks them against your device clock and shows a colored badge: active (green), not yet valid (amber), or expired (red). If your clock is wrong, the badge will be wrong.
How does the share link work?
Click Copy share link. The token is base64-encoded into the URL fragment (the part after #). The fragment is never sent to a server — it only exists in your browser. The secret or public key is NEVER included in the share link. Anyone with the link sees the same decoded token, but must supply their own key to verify.
Why does the RS256 / ES256 sample button say "fresh key"?
Every click generates a brand-new RSA or ECDSA keypair using WebCrypto, signs a sample payload, and shows you the public key (as JWK) alongside the token. Verification works because we just signed it. The private key is never displayed and is discarded when you reload the page.
My token "looks decoded but verification fails." What is wrong?
Common causes: wrong key (the token was signed by a different key than the one you pasted); whitespace in the JWK JSON (sometimes browsers strip newlines from copied PEMs — paste raw); algorithm mismatch (the header says RS256 but you pasted an ECDSA key); or the token was tampered with (a single character change in header or payload invalidates the signature). Try the included samples to confirm the tool itself works, then bisect from there.
Is this tool really free?
Yes. No signup, no token logging, no usage limit, no ads.