KKwikfig.

JWT Decoder

Decode a JSON Web Token's header and payload in your browser — claims in a table, exp and iat as real dates, expiry judged against now. Decoding only, never verification. Runs entirely in your browser — your numbers never leave this device.

Decoding is not verification: this tool does not check the signature, so a decoded token proves nothing about authenticity.

JWT
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
Payload claims
ClaimValue
sub1234567890
nameJohn Doe
iat1516239022
Status vs now
No exp / nbf claims to check
Issued at (iat)
1516239022 (2018-01-18T01:30:22.000Z)
Expires (exp)
—
Not before (nbf)
—
Signature segment
Present (not checked)

How it works

JWT = base64url(header JSON) . base64url(payload JSON) . base64url(signature) | Decode = reverse the base64url of segments 1 and 2 and parse the JSON | Status: expired if now ≥ exp, not-yet-valid if now < nbf — a reading of claims, not a check of the signature
Claims you will meet most often in a payload
ClaimMeansHow this tool shows it
subSubject — who the token is aboutAs written, in the claims table
issIssuer — who signed and issued itAs written
audAudience — who it is intended forAs written
iatIssued at (epoch seconds)As a number and as a UTC date
expExpires at (epoch seconds)As a number, a UTC date, and an expired / not-expired judgement
nbfNot valid before (epoch seconds)As a number, a UTC date, and a not-yet-valid judgement

A JSON Web Token is three base64url segments joined by dots: a header naming the signing algorithm, a payload of claims, and a signature. Decoding is the easy half of working with one — reverse the base64url of the first two segments, parse the JSON, and you can read everything: who issued it, who it describes, when it expires. This tool does exactly that, lays the claims out in a table, reads the numeric date claims (iat, exp, nbf) as real dates, and judges the token's time window against the current moment.

Decoding is not verification: this tool does not check the signature, so a decoded token proves nothing about authenticity. Anyone can write any claims into a token — decoding shows you what a token says, never whether you should believe it. Belief requires checking the signature with the issuer's key, which belongs in your own backend code with a vetted library, not in a web page you pasted a credential into. Treat anything you decode here as an unauthenticated claim, because cryptographically that is all it is.

Two practical notes. The payload of a standard JWT is not encrypted — base64url is an encoding anyone can reverse, as this page demonstrates — so tokens must never carry secrets. And the expiry judgement is only as meaningful as the claims: a token with no exp never 'expires' by its own text, which the tool reports as having no time claims rather than calling it valid.

Worked examples

The classic demo token, decoded

Input
Token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflK… (the jwt.io example)
Working
Segment 1 base64url-decodes to the header JSON: alg HS256, typ JWT. Segment 2 decodes to the payload: sub 1234567890, name John Doe, and iat 1516239022 — which the timestamp reading gives as 2018-01-18 01:30:22 UTC. There is no exp claim, so the status is 'no time claims', not 'valid'.
Result
Header {"alg":"HS256","typ":"JWT"} · Payload {"sub":"1234567890","name":"John Doe","iat":1516239022}

Reading a validity window

Input
Payload = {"sub":"u1","exp":2000000000,"nbf":1000000000}, judged at now = 1700000000
Working
exp 2000000000 is 2033-05-18 03:33:20 UTC and nbf 1000000000 is 2001-09-09. Now (1700000000, November 2023) sits between them, so the claims describe a token inside its window. Judge the same token at 2100000000 instead and exp is in the past: expired.
Result
Status at now = 1700000000: within its validity window; at 2100000000: expired

Frequently asked questions

Does decoding a token here check that it is genuine?

No — and nothing on this page claims to. Decoding is not verification: this tool does not check the signature, so a decoded token proves nothing about authenticity. The signature segment is reported as present or absent and left alone. Verification needs the issuer's key and a proper library in your own systems.

Is it safe to paste a real token?

The decoding runs entirely in your browser — the token is never uploaded or stored. That said, a live bearer token is a credential: anyone holding it can use it until it expires, so treat it with the same care as a password, decode copies rather than production tokens where you can, and never post one in a bug report or chat.

Can I edit a decoded claim and re-encode the token?

You can edit the JSON and base64url-encode it with the Base64 tool, but the result will not be accepted anywhere the signature is checked — changing one byte of the payload invalidates the signature, which is the entire point of signing. An edited token is useful only for testing how a decoder or a test harness reads claims.

Why does my token show as expired when the app still accepts it?

Two common reasons: the judgement here uses your device's clock, and a wrong system clock skews it; and many systems allow a small leeway (often 30–60 seconds) around exp and nbf for exactly that skew. A token hours past exp that still works is a server that is not checking expiry — a real finding, not a tool error.

What does 'no time claims' mean?

The payload carries neither exp nor nbf, so by its own text the token has no time window to judge — like the demo token in the worked example, which has only iat. It does not mean the token is valid forever in practice; issuers and servers can enforce lifetimes the token itself does not state.

What is the third segment?

The signature: the header and payload, signed with the algorithm named in the header (HS256 in the demo token) using a secret or private key held by the issuer. This tool shows it as present/absent only — reading it tells you nothing without the key, and checking it is deliberately out of scope here.

Related tools

More in Developer Tools · Browse all tools