How-to Guide 5 min read

How to Check If a JWT Has Expired (exp, iat and nbf Explained)

Check whether a JWT is expired by reading its exp claim, convert iat and nbf to dates, and fix common errors such as millisecond timestamps and clock skew.

check jwt expirationjwt exp claimdecode jwt expiryjwt iat nbfjwt token expired

The short answer

A JWT has expired when the current time is at or after the value in its exp claim. exp is a Unix timestamp in seconds, so you convert it to a date and compare it with now. Paste the token into the JWT Decoder and it reads exp and iat for you, shows both as dates in your local time, and marks the token Expired or Valid based on the expiry time alone.

The three time claims in a JWT

The JWT standard (RFC 7519) defines three optional time claims. All three use "NumericDate": the number of seconds since 1970-01-01 00:00:00 UTC.

ClaimNameWhat it means
expExpiration timeThe token must not be accepted on or after this time
nbfNot beforeThe token must not be accepted before this time
iatIssued atWhen the token was created; useful for working out its age

None of them is mandatory in the standard. Your API or identity provider decides which ones it sets and checks. Many access tokens carry exp and iat; some also carry nbf.

How to check expiry with the decoder

  • Copy the full token, all three parts separated by dots. If it came from an Authorization header, drop the word Bearer and the space before pasting.
  • Paste it into the JWT Token box. The three parts are shown in different colours so you can see where each starts.
  • Read the status bar under the token:
  • - ✓ Valid JWT structure means the header and payload decoded as JSON.

    - ⚠ Expired or ✓ Valid appears only if the payload has an exp claim, followed by the expiry date and time.

    - Issued: shows the iat date and time, if present.

  • Open the Payload tab to see every claim, including nbf, sub, aud, iss and any custom ones. Copy JSON copies the decoded payload.
  • Dates are shown in your browser's local time zone. A token that "expires at 8:30 PM" in India expires at 15:00 UTC.

    Worked example

    Here is a payload from a short-lived access token:

    {"sub":"user_42","iat":1791900000,"nbf":1791900000,"exp":1791903600}

    Converting each value:

    • iat 1791900000 = 13 October 2026, 14:00:00 UTC (7:30 PM IST)
    • nbf 1791900000 = the same moment, so the token is usable immediately
    • exp 1791903600 = 13 October 2026, 15:00:00 UTC (8:30 PM IST)

    exp minus iat is 3,600 seconds, so this token lives for 60 minutes. Any request after 8:30 PM IST that day should be rejected with this token, and the client should use a refresh token or sign in again.

    If you need to convert a timestamp by hand, the Unix Timestamp Converter does it, and the guide to Unix timestamps, seconds vs milliseconds explains the formats.

    Checking nbf yourself

    The decoder does not evaluate nbf. If your token has it, compare it with the current time:

    • If now is earlier than nbf, a correct server will reject the token as "not yet valid", even though it is not expired.
    • This often shows up when the server that issued the token and the server checking it have clocks a little apart.

    The standard allows a small leeway, usually no more than a few minutes, for clock differences. Many JWT libraries have a setting for it (often called leeway or clock tolerance).

    Why a token can be rejected even though it shows "Valid"

    The Valid label in the decoder only means "the exp time has not passed yet". It does not mean the token will be accepted. A server may still reject it because:

    • The signature is wrong. The decoder does not verify signatures; that needs the secret or public key, and should happen on your server. Anyone can edit a payload and re-encode it, so never trust decoded claims on their own.
    • nbf is in the future, as above.
    • The audience or issuer does not match. Check aud and iss in the payload against what your API expects.
    • The token was revoked. Logging out, a password change or an admin action can invalidate tokens on the server side before exp.
    • Clock skew. If your server's clock runs fast, it may see the token as expired a minute or two early.

    Common mistakes with exp

    Using milliseconds instead of seconds

    JavaScript's Date.now() returns milliseconds. If a developer writes that straight into exp, the value is 1,000 times too large. 1791903600000 read as seconds is a date in the year 58753, so the token effectively never expires. Real expiry values today are 10 digits long; 13 digits is a red flag.

    The opposite mistake happens when reading: new Date(exp) in JavaScript treats the number as milliseconds, so new Date(1791903600) gives 21 January 1970. Multiply by 1,000 first: new Date(exp * 1000).

    Forgetting time zones

    exp is always UTC-based. The decoder shows it in your local time, but logs on your server may print UTC. When comparing, make sure both are in the same zone.

    Treating a missing exp as "valid forever"

    If the decoder shows no expiry line, the token has no exp claim. That is allowed by the standard, but for access tokens it is usually a security risk, because a leaked token keeps working until the signing key changes.

    Very long lifetimes

    An access token that lives for days or months gives an attacker a long window if it leaks. Short-lived access tokens with a separate refresh process are the common pattern.

    Privacy and safety tips

    The decoder splits the token and Base64URL-decodes the header and payload in your browser. Even so, treat production tokens like passwords:

    • Prefer test tokens, or tokens that have already expired, when debugging.
    • Do not paste live tokens into chat apps, tickets or screenshots.
    • Remember that a JWT payload is encoded, not encrypted. Anyone with the token can read its claims, so never put secrets in it.

    New to JWTs? Start with what a JWT token is and how it works, and see the Base64 guide for how the Base64URL encoding in each part differs from standard Base64.

    Frequently asked questions

    How do I know if a JWT is expired?

    Read the exp claim in the payload. It is a Unix timestamp in seconds; if the current time is at or after it, the token has expired. The JWT Decoder shows Expired or Valid with the date.

    Is exp in seconds or milliseconds?

    Seconds since 1 January 1970 UTC, as defined in RFC 7519. A 13-digit exp value usually means someone wrote milliseconds by mistake.

    Does the decoder verify the JWT signature?

    No. It decodes the header and payload and checks exp against the current time. Signature verification needs the secret or public key and should happen on your server.

    What is the nbf claim?

    Not before: the time before which the token must not be accepted. The decoder shows it in the Payload tab but does not evaluate it, so compare it with the current time yourself.

    Try this tool on Lazyblink

    Put this guide into practice with our free online tool — no signup required.

    Open tool