JWT Decoder
This free JWT decoder reads the header, payload and signature in your browser and explains what each registered claim means. Expiry is shown in plain English rather than a Unix timestamp, the nbf claim behind mystery 401 errors is flagged, alg none is warned about, and HMAC signatures can be verified locally.
What does this decoder do?
It splits a JWT into its three parts, decodes them, and then does the part that usually gets left to you: it explains what the token actually says.
- Every registered claim explained.
iss,sub,aud,exp,nbf,iatandjtiappear with their value and what they are for, next to each other. - Expiry in plain English. "expired 3 hours ago" or "expires in 12 minutes", instead of
1758304800. - The
nbfdiagnosis. When a token decodes cleanly but is not valid yet, that is called out first, because it is the cause of the 401 that looks like nothing is wrong. - Warnings that matter:
alg: none, a missingalg, an empty signature, aniatin the future, and timestamps written in milliseconds by mistake. - HMAC verification with the browser's own crypto engine, for HS256, HS384 and HS512.
- Copy or download the full decoded output as JSON. A
Bearerprefix, quotes and stray whitespace are stripped for you.
The 401 that makes no sense
A token decodes fine. exp is hours away. The API still answers 401.
The usual cause is nbf, the "not before" claim. It marks the moment before which a verifier must refuse the token, and a token minted slightly ahead of time, or issued by a server whose clock runs fast, fails this check while looking perfectly healthy.
| Claim | What it does | Can it cause a 401? |
|---|---|---|
exp | Token stops being accepted after this | Yes, and everyone checks it |
nbf | Token is not accepted before this | Yes, and almost nobody checks it |
iat | Records when the token was issued | No, it only records age |
All three are NumericDate values: seconds since 1 January 1970. JavaScript works in milliseconds, so multiplying by a thousand is a frequent mistake, and a timestamp that lands in the year 57000 is the symptom. This page flags that too.
What this page loads, precisely
There is a well-documented worry about pasting JWTs into web tools, and it deserves a straight answer rather than a slogan.
What is true here: your token is decoded by JavaScript already running in your browser. No network request carries it. Nothing is uploaded, logged or stored, and closing the tab clears it.
What is also true: this page loads two third-party scripts, like every page on this site: Vercel Analytics, which counts page views, and the Supabase client used for the optional account system. Neither reads the token, but if your threat model does not allow any third-party JavaScript on the page at all, that is a legitimate position and you should not take our word for it.
For that case, here is the command that makes this page unnecessary:
cut -d. -f2 <<< "$TOKEN" | base64 -d 2>/dev/null | jq
Telling you that costs us a visit and is still the right thing to print.
What this tool does not do
- It does not decode JWE. Encrypted tokens have five parts, and their contents cannot be read without the decryption key. No decoder can show you what is inside one.
- It does not validate
issoraudagainst your server. It shows them and explains them, but only the server meant to accept the token knows which values are correct. - It does not verify RSA or ECDSA signatures yet. Only HMAC. RS256 and ES256 need a public key and more handling, and half-doing it would be worse than saying no.
- It does not create or sign tokens. This is a decoder.
- It does not tell you a token is safe. A valid signature proves the token was not altered. It says nothing about whether the claims inside deserve the access they ask for.
Is my data private?
Yes, with the precision above. The decoding is local, the token never travels, and the HMAC verification also runs in your browser using the Web Crypto API. Note that verification needs your signing secret, and a production signing secret is far more sensitive than the token itself, so think twice before pasting one into any web page, this one included.
Frequently asked questions
Why does my JWT return 401 when it decodes fine and has not expired?
The usual cause is the nbf claim, not exp. A token can decode perfectly and still be rejected because nbf sets the moment before which it must not be accepted. This decoder checks nbf first and says so directly, because it is the failure that looks like nothing is wrong.
What do exp, nbf and iat actually mean?
They are NumericDate values, seconds since 1 January 1970. The exp claim is when the token stops being accepted, nbf is when it starts being accepted, and iat only records when it was issued. Only exp and nbf gate acceptance; iat records age and nothing more.
Why does my exp look like a huge wrong number?
Because it was probably written in milliseconds. JavaScript works in milliseconds but NumericDate is seconds, so multiplying by a thousand is a common mistake. This decoder spots values that are far too large, tells you they look like milliseconds, and still interprets them sensibly.
Is my token sent to a server?
No. The token is decoded by JavaScript running in your browser, and no network request carries it anywhere. Nothing is uploaded, logged or stored. Read the section below about what this page does load, because being precise about that matters more than a blanket privacy claim.
Can it verify the signature?
It verifies HMAC signatures, meaning HS256, HS384 and HS512, using the browser's own crypto engine. Verification needs your signing secret, and pasting a production secret into any web page is a larger risk than pasting the token, so the warning sits next to the field.
What does alg none mean and why is it flagged?
It means the token carries no signature at all, so anyone can change the payload and it will still look structurally valid. Some libraries historically accepted such tokens by mistake. When a header says alg none, this decoder says so plainly instead of quietly showing the claims.
Does it decode encrypted tokens?
No. It reads JWS, the signed format with three dot-separated parts that almost every API uses. JWE, the encrypted format, has five parts and its contents cannot be read at all without the decryption key, so no decoder can show you what is inside one.
Does it check whether the issuer and audience are correct?
It shows the iss and aud values and explains what they are for, but it cannot judge them. Whether an issuer or audience is correct depends on the server meant to accept the token, and nothing in the token itself says which server that is.
Why does pasting Bearer before the token still work?
Because it is stripped automatically, along with surrounding quotes and whitespace. Tokens are usually copied straight out of an Authorization header or a JSON response, so they arrive with that prefix attached, and failing on it would waste your time for no reason.
Can I save the decoded output?
Yes. Copy sends the decoded header and payload to your clipboard, and Download saves them as a JSON file. Both give you the full decoded content rather than what happens to fit on screen, which matters for tokens carrying long permission or role lists.
Related tools
DeveloperBase64 Encoder / DecoderEncode text, images and files to Base64, and decode them back.
DeveloperJSON FormatterFormat, beautify, and validate JSON right in your browser.
DeveloperTimestamp ConverterConvert Unix timestamps to dates and back, in any unit.- DeveloperHash GeneratorHash text or files, and check a download really is what it claims.
DeveloperToken CounterCount tokens exactly, check the context window, estimate the cost.
Rate JWT Decoder & help shape it
This tool is free and still growing. Tell us what works, what you would change, and what is missing. Your feedback is what decides what we build next.
Last updated: September 19, 2026