Security

JWT Decoder

Decode and inspect JSON Web Tokens with signature verification.

Encoded
Header
Payload
Signature
Algorithm: HS256Type: JWTValid

Token Structure

HEADER
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
PAYLOAD
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE5MTYyMzkwMjJ9
SIGNATURE
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Standard Claims

Subject (sub)1234567890
Expiration (exp)9/21/2030, 4:37:02 PM
Issued At (iat)1/18/2018, 1:30:22 AM

Verify Signature

Decoded

Header

Decoded

Payload

Three segments, one JSON.parse each, and nothing more

A JWT is three base64url segments joined by dots — header, payload, and signature — and that is exactly what this tool works with. It splits the token on its dots, and if there are not exactly three parts, it stops immediately with "Invalid JWT: must contain 3 parts." rather than guessing at a partial token. The first two segments are base64url-normalized (dashes and underscores swapped back to standard characters, padding restored based on the segment's length) and run through atob, then JSON.parse, to produce the header and payload objects shown on the right. The third segment — the signature — is never decoded or interpreted at all; it is returned and displayed as the plain string it already is.

What this decoder actually verifies: nothing

There is no cryptography anywhere in this tool's decoding logic — no HMAC, no RSA, no ECDSA, nothing that checks whether a signature is genuine. The "Verify Signature" panel accepts a secret key, but typing one does not run a check against it; it only reveals a note stating that real signature verification requires cryptographic libraries this page does not include. Decoding a token and verifying it are two different operations, and this page performs only the first. A token that decodes cleanly here has a well-formed structure — that is all it proves.

What the "Expired" and "Valid" badge actually checks

The status badge reads a single claim: exp. If the payload has no exp field at all, the badge does not appear — there is nothing to compare against. When exp is present, the badge compares it against the current time and reports "Expired" or "Valid" accordingly. "Valid" means exactly one thing here: the token has not passed its own stated expiry time. It says nothing about who issued the token, whether its signature is genuine, or whether it has been altered since it was signed — an attacker who edits a payload and re-encodes it produces a token that decodes here identically to a real one, badge included, because nothing about decoding or the expiry check can detect that.

iss, sub, aud, and nbf are displayed, not enforced

The Standard Claims panel surfaces every recognized field it finds — issuer, subject, audience, expiration, not-before, issued-at, and JWT ID — converting the three time-based ones into a readable local date and time. None of these values are checked against anything else on this page: a token whose nbf (not valid before) claim lies in the future is still shown, not rejected, and an aud value is displayed exactly as written with no comparison against an expected audience. Reading these claims here is for inspection, not for deciding whether a token should be trusted by an application.

One token, decoded exactly

The page loads with a sample token already pasted in. Its header decodes to {"alg":"HS256","typ":"JWT"} and its payload to {"sub":"1234567890","name":"John Doe","iat":1516239022,"exp":1916239022} — that exp claim corresponds to a date decades from now, which is why this particular demo token always shows "Valid" no matter when the page is loaded. That is a property of this one sample token, not something the page arranges — a token with an exp in the past would show "Expired" the same way.

Before pasting a production token here

Decoding runs entirely in the browser and nothing is sent to a server — that part of the client-side claim is accurate. But a JWT payload is only base64-encoded, not encrypted, so anything in it — user IDs, email addresses, internal role names — is fully readable the moment it is decoded, by this tool or any other. Pasting a live production token here (or into a screenshot, a bug report, or a chat message) exposes that payload in plain text to whoever sees it next; a redacted or already-expired token is the safer choice for demonstrating a problem to someone else.

Common use cases

Debugging an OAuth or OIDC integration

Paste an access or ID token to see its claims laid out — issuer, audience, and expiry — while diagnosing why an auth flow is behaving unexpectedly.

Confirming a token has actually expired

Check the exp claim and the Valid/Expired badge before assuming an API's 401 response is caused by something other than an expired token.

Checking which algorithm a token declares

Read the alg field in the decoded header before wiring up server-side signature verification for that same token type.

Diagnosing a malformed token

Paste a token that a client is rejecting and see exactly which of the three required dot-separated segments is missing or invalid.

Frequently asked questions

Does this tool verify the JWT's signature?

No. It decodes the header and payload and displays the raw signature segment, but nothing in this page performs the cryptographic check that would confirm a signature is genuine.

What does the green "Valid" badge actually confirm?

Only that the exp claim, if present, has not yet passed. It does not confirm the token was issued by a trusted party, that its signature checks out, or that it has not been altered.

Why does typing a secret key in the Verify Signature box do nothing visible?

That field does not run a signature check — it exists alongside a note explaining that real verification needs cryptographic libraries this page does not include. Nothing is computed from the value you type there.

What happens if my token does not have three dot-separated parts?

Decoding stops immediately with "Invalid JWT: must contain 3 parts." rather than attempting to decode a partial token.

Are nbf, iss, and aud checked against anything?

No — they are parsed and displayed exactly as found in the payload. A token with a not-before date in the future, or an audience that does not match your application, is shown without any warning.

Is my JWT ever sent to a server?

No. Splitting, decoding, and displaying the token all happen in your browser using plain JavaScript; nothing about the token is transmitted anywhere.

Why does the example token always load as "Valid"?

Its exp claim is set decades in the future, so the expiry check never trips. Paste a token with an exp in the past and the badge switches to "Expired" the same way.

Should I paste a real production access token here?

Only if you accept that its payload — every claim inside it — becomes fully readable in plain text on your screen. Nothing is uploaded, but the token is not encrypted, so anyone who later sees your screen or a screenshot sees the same claims you do.

You might also like