The JWT Decoder unpacks a JSON Web Token in your browser: paste the token and it separates the three segments, base64url-decodes and pretty-prints the header and payload as JSON, shows the raw signature segment, and, when the payload carries an exp claim, reports whether the token is currently valid, expired, or has no expiry, with the minutes remaining. Nothing is sent to a server, which matters because tokens are credentials.
How It Works
A compact JWT is three base64url strings joined by dots: header, payload, signature. The decoder converts base64url back to standard base64 (swapping - and _ and restoring padding), decodes the bytes as UTF-8, and parses the first two segments as JSON. The third segment is displayed as-is, since a signature is binary data, not readable text. The expiry check simply compares the exp claim (seconds since the epoch) with the current time.
What the claims mean
| Claim | Name | Meaning | |---|---|---| | iss | Issuer | Who issued the token | | sub | Subject | Who or what the token is about, usually a user ID | | aud | Audience | Which service the token is intended for | | exp | Expiry | Unix time after which the token must be rejected | | iat | Issued at | Unix time of issuance | | nbf | Not before | Unix time before which the token must be rejected | | jti | JWT ID | Unique token identifier, used for revocation lists |
The header typically carries alg (the signing algorithm, such as HS256 or RS256) and typ (JWT), plus kid when a key ID selects among several signing keys.
Worked reading of a token
A header of {"alg":"HS256","typ":"JWT"} announces an HMAC-SHA256 signature, common for first-party services; RS256 signals RSA signatures verified against a public key, typical of identity platforms. A payload with sub "user_4821", a ten-minute gap between iat and exp, and an aud naming the API tells you a short-lived access token pattern. If the decoder reports the token as expired while your application still accepts it, suspect clock skew or a server that skips validation; if it reports valid while the API rejects it, the cause lies in audience, issuer, or signature checks, none of which decoding alone can see.
Decoding is not verifying: the security section
Anyone can decode a JWT; the contents are encoded, not encrypted. The signature is what makes a token trustworthy, and this decoder does not verify it, so a tampered payload decodes just as happily as a genuine one. Three rules follow. Never paste production tokens into websites you do not control (this one processes locally, which is the only acceptable pattern). Never make authorization decisions client-side from decoded claims without server verification. And treat any token you see in a screenshot, log, or ticket as compromised if it is still within its validity window, and revoke or rotate it.
Limitations
The decoder parses exactly the compact three-segment form with valid base64url JSON in the first two segments; JWE-encrypted tokens (five segments) and malformed or non-JSON payloads return an error. Expiry status is evaluated against your device clock and the exp claim alone; nbf, audience, issuer, and signature validity are displayed for you to judge, not enforced here.
Frequently Asked Questions
Is it safe to paste a token here?
The processing happens locally in your browser and the token is not transmitted, which is the safe pattern for a decoder. General rule stands: prefer decoding tokens you own, on tools that run locally, and rotate any token that has been shared elsewhere.
Why does the payload decode but the API still rejects the token?
Decoding only proves the token is well-formed. Rejection is usually signature verification (wrong or rotated key), audience or issuer mismatch, or a revoked jti, none of which decoding can evaluate.
What does it mean if there is no exp claim?
The token never expires by its own terms, which the decoder reports as no-expiry status. Long-lived tokens are a security smell outside narrow machine-to-machine designs; most access tokens should live for minutes, not months.