Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path
JWT Decoder
A client-side JWT decoder. Paste a JSON Web Token and instantly see the decoded header and payload, with the standard claims (iss, sub, aud, exp, iat, nbf) explained and the expiry shown as a live countdown. Everything runs in your browser — the token is never sent anywhere, so it is safe to paste a real one.
Header
{
"alg": "HS256",
"typ": "JWT"
}Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}Registered claims
sub1234567890Subject — who or what the token is about.iat1516239022 → Jan 18, 2018, 7:00:22 AMIssued-at — when the token was created.
A JWT looks cryptic, but two of its three parts are plain JSON you can read. The token is three base64url segments separated by dots, and only the signature is opaque. This decoder turns the first two back into JSON, lists the standard claims in plain language and tells you, against your own clock, whether the token is valid right now.
What it computes
token = base64url(header) . base64url(payload) . base64url(signature)
decode = replace - with +, _ with /, pad with = to a multiple of 4,
Base64-decode, read as UTF-8, parse as JSON
- The header names the signing algorithm in
alg, shown beside the status, and usually the type intyp. - The payload holds the claims. Seven registered names from RFC 7519 get an explanation when present:
ississuer,subsubject,audaudience,expexpiration,iatissued at,nbfnot before andjtitoken ID. - Time claims are Unix seconds. Each is shown with its local date and time.
- The status is “not valid yet” if now is before
nbf, “expired” if now is at or afterexp, “valid” otherwise, and a no-expiry notice when neither claim exists. It refreshes every second.
A worked example
The page loads with the well-known example token from jwt.io. Its header segment, eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9, is 36 characters, already a multiple of four, and decodes to:
{
"alg": "HS256",
"typ": "JWT"
}
The payload segment is 74 characters, so the tool adds two = before decoding:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
| Field | Shown as | Meaning |
|---|---|---|
| alg | HS256 | HMAC with SHA-256, a shared-secret signature |
| sub | 1234567890 | The user or entity the token is about |
| iat | 1516239022, with its local time | Issued on January 18, 2018 at 01:30:22 UTC |
| name | In the payload only | A custom claim, not one of the seven registered names |
There is no exp and no nbf, so the status reads No exp claim — this token has no expiry. The signature, 43 characters, is 32 bytes of HMAC-SHA256 output; jwt.io documents the secret behind it as your-256-bit-secret, which is exactly why it should never be used for anything real.
Assumptions and limits
- No signature check. The tool never asks for a key, so a decoded token proves nothing about who issued it or whether it was altered.
- Signed tokens only. Encrypted JWE tokens have five parts and an unreadable payload; they cannot be decoded without the key.
- Your clock decides the status. Validity is computed from your device’s time, with no leeway, so a skewed clock gives a wrong verdict.
- Only seven claims explained. Custom and provider-specific claims, such as scopes or roles, appear in the payload without notes.
How to use the result
- Debug a 401 quickly. Check
exp, thenaudandissagainst what the API expects; a mismatch there causes most rejected tokens. - Keep secrets out of payloads. Anyone with the token can read every claim, so never put passwords, keys or personal data you would not show the user.
- Prefer short lifetimes. Minutes to an hour for access tokens limits the damage if one leaks; renew with a refresh flow instead.
- Pin the algorithm on the server. Verify with an allow-list of expected algorithms, and reject
alg: none.
How it works
- Splits header.payload.signature and base64url-decodes each part.
- Explains the registered claims: iss, sub, aud, exp, iat, nbf, jti.
- Shows a live valid, expired or not-yet-valid status from exp and nbf.
- Runs 100% in your browser; the token is never sent anywhere.
Frequently asked questions
What is a JWT made of?
A JSON Web Token is three base64url-encoded segments joined by dots: header, payload and signature. The header names the signing algorithm, such as HS256 or RS256, and the token type. The payload holds the claims, statements such as who issued the token (iss), who it is about (sub), who it is for (aud) and when it expires (exp). The signature covers the first two parts so tampering can be detected. The first two parts are only encoded, not encrypted, so anyone can read them.
Is it safe to paste a real token here?
The decoder runs entirely in your browser with JavaScript; the token is never sent to a server, logged or stored by the tool. Even so, a JWT is a credential: while it is unexpired, anyone holding it can often use it to call the API it was issued for. Treat it like a password, prefer test or expired tokens when you can, and never paste live tokens into tools that decode on a remote server.
Can this tool verify the signature?
No, and that is intentional. Verifying a signature requires the shared secret for HMAC algorithms or the issuer’s public key for RSA and ECDSA, and typing secrets into a web page is a bad habit. This tool decodes and inspects the token so you can read its claims and check its timing while debugging. Real verification must happen in your server or API gateway with the correct key, and nothing in a token should be trusted until it has passed that check.
What do exp, iat and nbf mean?
They are the standard time claims, written as Unix timestamps in seconds since 1970-01-01 UTC. exp, expiration, is the moment at or after which the token must be rejected. iat, issued at, is when it was created. nbf, not before, is the earliest time it may be accepted. This tool converts each to a readable local time and shows whether the token is currently valid, already expired or not yet active, the same three states a server enforces.
What is base64url encoding?
It is ordinary Base64 with two characters swapped so the result is safe in URLs and HTTP headers: a minus sign replaces the plus sign, an underscore replaces the slash, and the trailing equals-sign padding is dropped. To decode a JWT segment by hand, swap those characters back, add equals signs until the length is a multiple of four, and run a normal Base64 decode. That is exactly what this tool does before parsing the JSON.
Why does a token look expired here but still work on the server?
Usually clock skew or leeway. This page compares exp against your device’s clock, and if your clock runs fast the token can look expired early. Many servers are also configured with a small leeway, from a few seconds to a few minutes, to tolerate drift between machines, so a token can be accepted a little after exp. The reverse also happens: a server with a slow clock can reject a token as not yet valid. Keep server clocks synchronized.