JWT Decoder
Decode and inspect JSON Web Tokens. View header, payload, and expiration status.
How to check if a JWT is expired
Paste the token above and read the exp claim in the payload. It is a Unix timestamp in seconds, not milliseconds, counted from 1 January 1970 UTC. If that number is smaller than the current time, the token is expired and any correctly configured API will answer 401 regardless of whether the signature is valid.
Two adjacent claims decide the same question and are worth reading at the same time. iat is when the token was issued, and nbf (not before) is the earliest moment it becomes usable. A token whose nbf is in the future is rejected exactly like an expired one, which is a classic symptom of clock skew between the auth service and the API when they run on different hosts.
What is actually inside a JWT
A JSON Web Token is three Base64url-encoded segments joined by dots: header.payload.signature. The header says which algorithm signed the token. The payload carries the claims. The signature is a cryptographic check over the first two segments.
The critical property for testers: the first two segments are encoded, not encrypted. Anyone holding the token can read every claim in it, including this page and including an attacker who captured it from a log file. Never put anything in a JWT payload that you would not print on a postcard.
| Claim | Meaning | What breaks when it is wrong |
|---|---|---|
exp | Expiry time, Unix seconds | 401 after the deadline passes, mid-test-run |
iat | Issued at | Reveals token age; useful when debugging refresh logic |
nbf | Not valid before | 401 immediately after issue when clocks are skewed |
iss | Issuer | Token from the staging auth service rejected by production |
aud | Audience | Valid token rejected by the wrong microservice |
sub | Subject, usually the user id | Tests pass as the wrong user without anyone noticing |
scope / roles | Permissions | 403 instead of 401; the token is valid but under-privileged |
Why a decoder cannot tell you the signature is valid
This is the honest limit of every client-side JWT tool, including this one. Verifying a signature requires the secret for HMAC algorithms, or the issuer’s public key for RSA and ECDSA. A decoder has neither, so it shows you the signature segment and the declared algorithm: it does not and cannot confirm the token is authentic.
What the header still tells you is worth checking. An alg of none on a token your system accepts is a critical finding, not a curiosity: it means the service may accept unsigned tokens. A mismatch between the algorithm you expect and the one in the header is worth raising too, because algorithm-confusion attacks depend on a server trusting the token’s own claim about how it was signed.
Debugging a 401 during API testing
- Decode the token and check
expfirst. Most 401s in a long test run are simply an expired token, not a broken assertion. - Check
audandiss. A token minted for one service or environment will be refused by another even while it is perfectly valid. - Check
scopeorroles. If the claims are missing the permission the endpoint needs, the correct status is 403: a service answering 401 there is itself a defect worth filing. - Confirm the transport. A token sent without the
Bearerprefix, or split across a line break by a copy-paste, fails before any claim is read. - Only then suspect the signature, and verify it in the service that owns the key rather than in any browser tool.
Pasting production tokens into online decoders
A JWT is a live credential until it expires. Pasting one into a service that sends it to a server hands that server a working session. This decoder runs entirely in your browser, the token is parsed by JavaScript on your machine and never leaves it, which is the reason the tool exists in this form. You can confirm that yourself in DevTools: open the Network tab, decode a token, and check that no request carries it as a payload.
Frequently asked questions
Can you decode a JWT without the secret key?
Yes. The header and payload are Base64url-encoded, not encrypted, so any decoder can read them without a key. The secret is only needed to verify the signature or to create a new valid token.
Is it safe to decode a JWT online?
It depends entirely on whether the tool sends the token anywhere. A decoder that posts the token to a backend has received a usable credential. A decoder that runs in the browser, like this one, does not transmit it. For a production token, prefer a browser-side tool or a local command-line decoder.
Why does my JWT say invalid signature?
Usually because the verifier is using a different key than the issuer, the token was copied incompletely, or the algorithm in the header does not match the one the verifier expects. A truncated token is the single most common cause: check that all three dot-separated segments are present.
What is the difference between JWT expiry and session expiry?
The exp claim is enforced by whoever validates the token and cannot be revoked early without extra infrastructure. A server session can be invalidated at any moment. This is why logout often fails to end access in JWT-based systems: a test worth writing explicitly.
Should JWTs be stored in localStorage?
It is common and it is risky: anything running JavaScript on the page can read localStorage, so one XSS defect becomes a stolen session. An httpOnly cookie is the safer default. If you are testing a product that stores tokens in localStorage, pair that with an XSS test rather than treating them as separate concerns.
How long should a JWT be valid?
Short: minutes to an hour for access tokens, with a longer-lived refresh token that can be revoked. When you see an exp months away, that is a finding: the token cannot be withdrawn if it leaks.