How to Check if a JWT Is Expired (Without Sending It Anywhere)
Read a JWT's exp, iat and claims in your browser and see expired: true or false at a glance. Step by step, how exp works, the same check in code, and what a decoder cannot tell you.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →An API that worked an hour ago answers 401 Unauthorized. The first question is almost always: has the token expired? A JWT carries its own expiry time, so you can answer that by reading it — no server call needed. This guide shows how to do it in the browser without pasting a live token into a site that uploads it, and how to do the same check in code.
How a JWT stores its expiry
A JWT is three base64url parts separated by dots: header.payload.signature. The payload is plain JSON:
{
"sub": "user_4821",
"role": "admin",
"iat": 1790812800,
"exp": 1790816400
}
iat (issued at) and exp (expires) are Unix timestamps in seconds (RFC 7519). The token is expired when the current time is at or past exp. Here exp − iat = 3600: a one-hour token.
Step by step
- Copy the token. From a request header, copy everything after
Bearer— the decoder also accepts the wholeBearer eyJ…value and strips the prefix. - Paste it into the JWT decoder. It decodes as you paste; nothing is sent to a server.
- Read the timestamps block:
iatandexpare shown as dates, and"expired": trueorfalseis computed from your computer's clock. - Compare tokens. Paste a freshly issued token: the
expiredflag should flip tofalse. If a fresh token is also rejected, the cause is not expiry — check the audience (aud), issuer (iss), scopes, or clock skew between servers.
The same check in code
JavaScript (browser or Node):const payload = JSON.parse(atob(token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/')));
const expired = Date.now() >= payload.exp * 1000;
Python:
import base64, json, time
part = token.split(".")[1]
payload = json.loads(base64.urlsafe_b64decode(part + "=" * (-len(part) % 4)))
expired = time.time() >= payload["exp"]
Multiply by 1000 in JavaScript: exp is in seconds, Date.now() in milliseconds — the most common bug in hand-written expiry checks.
Limitations — what a decoder cannot tell you
- It does not verify the signature. Decoding only reads the payload; anyone can create a token with any
exp. Your server must verify the signature with the secret or public key before trusting a claim. The decoder marks the signature as not verified for that reason. - "Not expired" does not mean "valid". A token can be revoked, issued for another audience, or signed with a rotated key and still have a future
exp. - Clock skew. The flag uses your machine's clock; servers usually allow a small leeway (often 30–60 seconds).
- Encrypted tokens (JWE, five parts) cannot be read without the key; the decoder says so instead of showing the payload.
- Treat live tokens as passwords even in a private tool: clear the box when you are done, and never paste production tokens into tools that send data to a server.
Related
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles