Text
JWT Decoder & Verifier
Decode any JSON Web Token in your browser — inspect the header and payload, humanize exp/iat/nbf, and optionally verify the HS256/384/512 signature with your secret. 100% client-side, nothing leaves the page.
Everything runs in your browser. Nothing is ever sent off this page.
Paste a token above. The decoded header, payload, and timing claims appear here automatically.
What this is and why it matters
JSON Web Tokens are the default currency of stateless authentication on the modern web. When you log into an API, the server typically hands back a signed JWT that your client stores and then attaches to every subsequent request in an Authorization header. The server can trust that token without a database lookup because the signature proves it was minted by a party holding the secret. This is what makes JWTs attractive for microservices, single-page apps, and mobile clients: the identity travels with the request instead of living in server-side session storage.
The catch, and the reason a decoder like this one matters, is that the header and payload are merely base64url-encoded, not encrypted. Any developer debugging an auth flow needs to see what claims a token actually carries — the subject, the issuer, the audience, the scopes, and the timing claims — because ninety percent of real-world JWT bugs are mundane: a clock skew that trips nbf, an exp that already passed, an audience that does not match, or a scope the backend expected but the issuer never granted. Reading the raw token by eye is impossible; a decoder turns it into legible JSON in one paste.
Verification is the other half of the story. A decoded token tells you what it claims, but not whether those claims are trustworthy. By recomputing the HMAC signature from the header, payload, and your shared secret, you can confirm a token was genuinely signed by the expected issuer and has not been altered in transit. Doing all of this locally in the browser — with no request to any server — means you can safely inspect tokens during development without leaking them to a third party.
How to use this tool
Copy the JWT you want to inspect. In a browser session it usually lives in local storage, a cookie, or the Authorization header of a network request under your dev tools. In a backend log it appears as a long three-part string that looks like eyJhbGci... with two dots in it. Copy the whole thing, dots included, and paste it into the token box above.
Read the decoded output. The tool splits the token on its dots, base64url-decodes the first two segments, and pretty-prints them as JSON in a monospace block — the header on top, the payload below. The header tells you the signing algorithm (the alg field) and token type. The payload holds the claims: sub for the subject, iss for the issuer, aud for the audience, plus any custom claims your application added.
Check the timing. If the payload contains iat, nbf, or exp, the tool shows both the raw epoch number and a human-readable date for each, so you do not have to convert seconds-since-1970 in your head. A green badge means the token is still within its validity window; a red Expired badge means the current time is past exp.
Optionally verify the signature. Enter the shared secret in the secret field. The tool reads the alg from the header, recomputes the HMAC with Web Crypto, and compares it against the signature segment. A verified badge means the secret and token match; a failed badge means the secret is wrong or the token was tampered with. Use the copy buttons to grab the header or payload JSON for a bug report.
Examples and use cases
Debugging a 401 that should be a 200
A frontend engineer keeps getting 401 Unauthorized from an API that worked yesterday. Pasting the stored token into this decoder reveals the payload exp is 1719800000 — a date two hours in the past. The badge flips red to Expired. The real bug is that the silent-refresh flow stopped firing, so the client kept sending a stale token. Seeing the humanized exp date immediately, instead of squinting at a raw epoch, turns a thirty-minute investigation into a ten-second one.
Confirming a backend signed a token with the expected secret
A backend developer suspects two services are configured with different HMAC secrets, causing intermittent signature failures. They grab a token minted by service A, paste it into the decoder, and enter the secret that service B is configured with. The verification badge reads failed. Swapping in service A’s secret flips it to verified. This confirms the two services are out of sync on the shared secret, which is exactly the kind of misconfiguration that is invisible in logs but obvious once you can test the HMAC locally.
Inspecting an unfamiliar third-party token
While integrating an OAuth provider, a developer receives an access token and needs to know what scopes and audience it carries before wiring up authorization checks. Decoding it exposes the aud claim pointing at the wrong resource server and a scope list missing the read:profile grant the integration needs. The header shows alg is RS256, so the tool notes that signature verification supports HS256, HS384, and HS512 only and skips the HMAC check gracefully — but the decoded claims already answer the question, letting the developer fix the authorization request upstream.
Frequently asked questions
- What is the difference between decoding and verifying a JWT?
- Decoding just base64url-decodes the header and payload so you can read the claims — it requires no secret and proves nothing about authenticity. Verifying recomputes the signature from the header, payload, and the signing key, then compares it to the signature in the token. Only verification tells you the token was really issued by the party you expect and has not been modified. This tool always decodes, and verifies the signature when you supply the HMAC secret.
- Is it safe to paste a real production token into this tool?
- Safer here than almost anywhere else, because everything happens locally. The token is split, decoded, and signature-checked entirely inside your browser tab using the Web Crypto API — no network request is made and nothing is stored. That said, the golden rule holds: never paste a live token into an AI chatbot, an online decoder whose code you cannot inspect, or any server-side tool, because the payload is readable and the signature could be captured and replayed. A JWT is a bearer credential; treat it like a password. This page is client-side only precisely so you do not have to take that risk while debugging.
- Why does the tool say it can only verify HS256, HS384, and HS512?
- Those are the HMAC algorithms, where the same shared secret both signs and verifies the token, so the check can run entirely in your browser with just the secret you type in. RS256, ES256, and PS256 are asymmetric — they are signed with a private key and verified with a matching public key. Verifying those would require you to paste in a PEM public key and adds a lot of surface area, so for now the tool decodes them fully and shows the claims, but skips the signature check with a clear note rather than pretending to verify.
- Why are exp, iat, and nbf shown as both a number and a date?
- Those claims are NumericDate values defined by the JWT spec as the number of seconds since the Unix epoch of 1970-01-01 UTC — not milliseconds, which is a common source of off-by-a-thousand bugs. The raw number is what actually travels in the token, but a human cannot read 1719800000 at a glance, so the tool also renders the corresponding calendar date and time. exp is when the token expires, iat is when it was issued, and nbf is the not-before time the token becomes valid.
- The payload looks readable — is a JWT encrypted?
- No. A standard signed JWT (a JWS) is only base64url-encoded, which is encoding, not encryption. Anyone who holds the token can decode and read every claim in the payload, exactly as this tool does. The signature protects integrity — it stops someone changing the claims without detection — but it does not hide anything. That is why you must never store passwords, card numbers, or other secrets inside a JWT payload. If you genuinely need the contents hidden, you want an encrypted JWE, which is a different construction.
- My token will not decode — what went wrong?
- The most common causes are copy-paste damage: a missing segment so the string does not have exactly two dots, stray whitespace or a line break in the middle, or an accidentally truncated payload. This decoder shows a friendly inline error instead of crashing, so re-copy the entire token, make sure you captured all three parts, and confirm there is no leading Bearer prefix left attached from an Authorization header.