JWT Decoder & Verifier — Free, Nothing UploadedSkip to content<br>Local-first<br>Decode and verify JWTs without uploading them.<br>Paste a token to read its header and payload, check the signature against your key, or sign a new one. Everything runs in your browser through WebCrypto — your tokens and your keys never leave this device.
Decode & verifySign a token<br>Paste a JSON Web TokeneyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cHeadereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9<br>PayloadeyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ<br>SignatureSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header{<br>"alg": "HS256",<br>"typ": "JWT"<br>}Payload{<br>"sub": "1234567890",<br>"name": "John Doe",<br>"iat": 1516239022
No "exp" claim, so this token never expires on its own. That is usually a mistake.<br>ClaimValuesub1234567890Subject — who or what the token is about, usually a user id.nameJohn DoeCustom claim — defined by whoever issued the token.iat2018-01-18T01:30:22Z — 1516239022 (3122 days ago)Issued at — when the token was created.
Header{<br>"typ": "JWT"<br>}The alg field is set from the algorithm you choose above.<br>Payload{<br>"sub": "1234567890",<br>"name": "John Doe"<br>Sign token
Uses the algorithm and key from the Key panel below.
AlgorithmHS256 — HMAC with SHA-256HS384 — HMAC with SHA-384HS512 — HMAC with SHA-512RS256 — RSASSA-PKCS1-v1_5 with SHA-256RS384 — RSASSA-PKCS1-v1_5 with SHA-384RS512 — RSASSA-PKCS1-v1_5 with SHA-512PS256 — RSASSA-PSS with SHA-256PS384 — RSASSA-PSS with SHA-384PS512 — RSASSA-PSS with SHA-512ES256 — ECDSA with P-256 and SHA-256ES384 — ECDSA with P-384 and SHA-384ES512 — ECDSA with P-521 and SHA-512<br>Key formatPlain secretBase64 secretPEM keyJWK
Secret or keyyour-256-bit-secretHMAC uses the same shared secret to sign and to verify.
Verify signature<br>Not checked yet — press Verify signature.
What the three parts actually are<br>A JWT is three base64url strings joined by dots. Only the third one involves cryptography — and none of them involve encryption.
headerWhich algorithm signed it<br>A small JSON object naming the signing algorithm in alg and usually the type in typ. It may also carry kid, a hint telling the recipient which of several keys to check against.
payloadThe claims — readable by anyone<br>The actual statements: who the token is about, who issued it, when it expires. This is encoded, not encrypted. Anyone holding the token can read it, so it must never contain a password or a secret.
signatureProof it was not edited<br>The first two parts are signed with a key. Changing a single character of the payload invalidates it. The signature proves integrity and origin — it does not hide anything.
Questions
Is it safe to paste a production token here?Yes, in the sense that nothing is transmitted. Decoding, verification and signing all run in your browser through the WebCrypto API, and there is no server to receive anything. You can confirm it in about a minute — jamuny.com/verify/ walks through four ways to check, including reading the Content-Security-Policy that makes it structurally impossible.<br>Does decoding a JWT require the secret?No, and this is the part people are most often surprised by. The header and payload are only base64url encoded, not encrypted, so anyone holding the token can read every claim inside it. The signature does not hide the contents — it only proves they have not been changed. Never put a password or anything private in a JWT payload.<br>What does “Invalid signature” actually tell me?That the token and the key you supplied do not match. Either you have the wrong key, or the token was altered after it was signed. It does not tell you which — that is the point of a signature. Check the algorithm in the header matches the one selected, since verifying an RS256 token with an HMAC secret will always fail.<br>Why is alg "none" dangerous?It means the token carries no signature at all, so anyone can edit the payload and it stays “valid”. Several libraries historically accepted it by default, which let an attacker change a user id to an admin id. If you see it outside a test fixture, treat it as a vulnerability.<br>Which key formats does this accept?HMAC algorithms take a plain or base64-encoded shared secret. RSA and ECDSA take a PEM public key for verifying and a PEM private key for signing, or a JWK for either. PKCS#1 keys (BEGIN RSA PRIVATE KEY) need converting to PKCS#8 first, because WebCrypto only reads PKCS#8.<br>Are my keys stored anywhere?No. Keys are imported into WebCrypto as non-extractable, which means even this page cannot read them back out once imported, and nothing is written to storage or sent anywhere. Closing the tab discards everything.