Loading calculators...
Fetching calculator categories and tools for this section.
Preparing tools and content for you. This usually takes a second.
Fetching calculator categories and tools for this section.
Quick answer
A JWT’s exp claim is a Unix timestamp in seconds (not milliseconds), and exp = iat + lifetime. 15 minutes = 900, 1 hour = 3,600, 24 hours = 86,400, 7 days = 604,800 seconds. A config value of 86400000 is milliseconds = 24 hours. To read exp as a date use new Date(exp * 1000): exp 1790943300 is 2026-10-02 12:15:00 UTC. The token is expired when now ≥ exp (plus any clock-skew leeway).
Paste a token to see when it expires in UTC and your local time, with a live countdown. Convert any exp or iat value — 10-digit seconds or 13-digit milliseconds — and turn lifetimes like 900, “15m”, “7d” or 86400000 into exp plus ready-to-use code for jsonwebtoken, jose, PyJWT, Java, Spring, .NET, Go and PHP.
Last updated October 2, 2026. Free, no sign-up. Guides: how to calculate JWT expiration · JWT clock skew
Decoded in your browser — nothing is sent anywhere. The signature is not verified.
.NET 300 · Spring 60 · most libraries 0
Status right now
Checking clock…
—
exp (UTC)
2026-10-02 12:15:00 UTC
1790943300 · local —
Lifetime (exp − iat)
15m
900 seconds · age —
| Claim | Raw value | UTC | Your time | Relative |
|---|---|---|---|---|
| Issued at (iat) | 1790942400 | 2026-10-02 12:00:00 UTC | — | — |
| Not before (nbf) | 1790942400 | 2026-10-02 12:00:00 UTC | — | — |
| Expires (exp) | 1790943300 | 2026-10-02 12:15:00 UTC | — | — |
Header
{
"alg": "HS256",
"typ": "JWT"
}Payload (claims)
{
"sub": "1234567890",
"name": "Jane Doe",
"iat": 1790942400,
"nbf": 1790942400,
"exp": 1790943300
}JWT times are NumericDate values: seconds since 1970-01-01T00:00:00Z (RFC 7519). Status uses this device’s clock.
A JWT expiry time is the exp claim in a JSON Web Token: the moment after which the token must be rejected. RFC 7519 defines exp, iat (issued at) and nbf (not before) as NumericDate values — the number of seconds since 1970-01-01T00:00:00 UTC, not milliseconds. The expiry is calculated as exp = iat + lifetime, so a 15-minute token issued at 1790942400 has exp 1790943300 (2026-10-02 12:15:00 UTC). To read it as a date, multiply by 1000 for a JavaScript Date or convert the seconds directly.
exp = iat + lifetime (seconds) · iat = floor(Date.now() / 1000)
date = new Date(exp × 1000) · expired ⇔ now ≥ exp + leeway · not yet valid ⇔ now < nbf − leeway
Example: a token issued at 1790942400 (2026-10-02 12:00:00 UTC) with a 15-minute lifetime gets exp 1790942400 + 900 = 1790943300 (2026-10-02 12:15:00 UTC). A verifier with 60 seconds of leeway still accepts it until 2026-10-02 12:16:00 UTC. If the issuer had written Date.now() + 900000 instead, exp would be a 13-digit millisecond value that libraries read as the year 58,000 — a token that never expires.
Use the seconds column for jsonwebtoken expiresIn numbers and for exp − iat; the milliseconds column for Java Date, Spring properties and JavaScript Date arithmetic.
| Lifetime | Seconds | Milliseconds | ms / jose string | ISO 8601 | Typical use |
|---|---|---|---|---|---|
| 1 minute | 60 | 60,000 | "1m" | PT1M | One-time links, step-up auth |
| 5 minutes | 300 | 300,000 | "5m" | PT5M | Keycloak and Spring Authorization Server default access token |
| 10 minutes | 600 | 600,000 | "10m" | PT10M | Auth0 MFA token (fixed) |
| 15 minutes | 900 | 900,000 | "15m" | PT15M | Common access-token lifetime |
| 30 minutes | 1,800 | 1,800,000 | "30m" | PT30M | Access token, internal apps |
| 1 hour | 3,600 | 3,600,000 | "1h" | PT1H | Firebase, Google, Cognito and Okta default |
| 2 hours | 7,200 | 7,200,000 | "2h" | PT2H | Longer browser sessions |
| 8 hours | 28,800 | 28,800,000 | "8h" | PT8H | Workday session limit |
| 10 hours | 36,000 | 36,000,000 | "10h" | PT10H | Auth0 ID token default |
| 12 hours | 43,200 | 43,200,000 | "12h" | PT12H | Shift-length sessions |
| 24 hours | 86,400 | 86,400,000 | "1d" | P1D | Auth0 access token default |
| 7 days | 604,800 | 604,800,000 | "7d" | P7D | Refresh token, remember-me |
| 14 days | 1,209,600 | 1,209,600,000 | "14d" | P14D | Refresh token |
| 30 days | 2,592,000 | 2,592,000,000 | "30d" | P30D | Cognito refresh token default; Auth0 access-token maximum |
| 90 days | 7,776,000 | 7,776,000,000 | "90d" | P90D | Okta org refresh token |
| 1 year | 31,536,000 | 31,536,000,000 | "365d" | P365D | Service tokens (prefer rotation) |
The same number means very different lifetimes depending on the unit. Plain numbers of whole minutes in milliseconds (like 86400000) are read as milliseconds; others as seconds.
| Value | Read as | Lifetime | Seconds |
|---|---|---|---|
| 300 | seconds (auto-detected) | 5m | 300 |
| 3600 | seconds (auto-detected) | 1h | 3,600 |
| 86400 | seconds (auto-detected) | 1d | 86,400 |
| 86400000 | milliseconds (auto-detected) | 1d | 86,400 |
| 604800000 | milliseconds (auto-detected) | 7d | 604,800 |
| "3600" | milliseconds (quoted string) | 3.6s | 3.6 |
| 15m | time span string (vercel/ms, jose) | 15m | 900 |
| 7d | time span string (vercel/ms, jose) | 7d | 604,800 |
| PT15M | ISO 8601 duration (Java Duration, Spring, XML) | 15m | 900 |
| 00:30:00 | .NET TimeSpan hh:mm:ss | 30m | 1,800 |
| ${jwt_expiration_ms:86400000} | milliseconds (from the name “jwt_expiration_ms”) | 1d | 86,400 |
| 1h30m | compound time span | 1h 30m | 5,400 |
iat = 1790942400 (2026-10-02 12:00:00 UTC).
| Lifetime | Seconds added | exp | Expires (UTC) |
|---|---|---|---|
| 5m | 300 | 1790942700 | 2026-10-02 12:05:00 UTC |
| 15m | 900 | 1790943300 | 2026-10-02 12:15:00 UTC |
| 1h | 3,600 | 1790946000 | 2026-10-02 13:00:00 UTC |
| 1d | 86,400 | 1791028800 | 2026-10-03 12:00:00 UTC |
| 7d | 604,800 | 1791547200 | 2026-10-09 12:00:00 UTC |
| 30d | 2,592,000 | 1793534400 | 2026-11-01 12:00:00 UTC |
10 digits are seconds, 13 are milliseconds. exp must be the seconds value.
| Value | Detected | UTC date | exp (seconds) |
|---|---|---|---|
| 1516239022 | 10 digits → seconds | 2018-01-18 01:30:22 UTC | 1516239022 |
| 1700000000 | 10 digits → seconds | 2023-11-14 22:13:20 UTC | 1700000000 |
| 1790942400 | 10 digits → seconds | 2026-10-02 12:00:00 UTC | 1790942400 |
| 1781624168859 | 13 digits → milliseconds | 2026-06-16 15:36:08.859 UTC | 1781624168 |
| 2000000000 | 10 digits → seconds | 2033-05-18 03:33:20 UTC | 2000000000 |
| 2147483647 | 10 digits → seconds | 2038-01-19 03:14:07 UTC | 2147483647 |
| Provider | Token | Default lifetime | Seconds | Configurable |
|---|---|---|---|---|
| Auth0 | Access token (custom API) | 24 hours | 86,400 | Up to 30 days (2,592,000 s) |
| Auth0 | ID token | 10 hours | 36,000 | Per application |
| Amazon Cognito | Access and ID token | 1 hour | 3,600 | 5 minutes to 1 day |
| Amazon Cognito | Refresh token | 30 days | 2,592,000 | 60 minutes to 10 years |
| Microsoft Entra ID | Access token | 60–90 minutes (random, ~75 avg) | 3,600–5,400 | Token lifetime policy |
| OAuth access token / ID token | 1 hour | 3,600 | No (user tokens) | |
| Firebase Auth | ID token | 1 hour | 3,600 | No |
| Okta (org server) | Access and ID token | 1 hour | 3,600 | Custom server: 5 minutes to 24 hours |
| Okta (org server) | Refresh token | 90 days | 7,776,000 | Custom server: 10 minutes to unlimited |
| Keycloak | Access token | 5 minutes | 300 | Realm or client setting |
| Spring Authorization Server | Access / refresh token | 5 minutes / 60 minutes | 300 | TokenSettings |
The JWT standard itself has no default lifetime, and most libraries add no exp unless you set one. OAuth responses report the access-token lifetime in seconds as expires_in.
| Library | Setting | Unit | Default |
|---|---|---|---|
| jsonwebtoken (Node) | clockTolerance | seconds | 0 (none) |
| jose (Node, browsers) | clockTolerance | seconds or "30s" | 0 (none) |
| PyJWT (Python) | leeway | seconds or timedelta | 0 (none) |
| jjwt (Java) | clockSkewSeconds() | seconds | 0 (none) |
| Spring Security resource server | JwtTimestampValidator(clockSkew) | Duration | 60 s (1m) |
| Microsoft.IdentityModel (.NET) | TokenValidationParameters.ClockSkew | TimeSpan | 300 s (5m) |
| golang-jwt v5 (Go) | jwt.WithLeeway() | time.Duration | 0 (none) |
| firebase/php-jwt (PHP) | JWT::$leeway | seconds | 0 (none) |
| Library | Code | Watch out |
|---|---|---|
| Node — jsonwebtoken | jwt.sign(payload, secret, { expiresIn: 900 }) // or '15m' | Number = seconds. A string with no unit is milliseconds: "60" = 60 ms. |
| Node — jose | new SignJWT(payload).setIssuedAt().setExpirationTime('15m') | String = time from now. A number is an absolute exp timestamp, not a lifetime. |
| Python — PyJWT | {"exp": datetime.now(tz=timezone.utc) + timedelta(seconds=900)} | PyJWT converts the datetime to Unix seconds. An int must already be seconds. |
| Java — jjwt | .expiration(new Date(System.currentTimeMillis() + 900000L)) | Java Date uses milliseconds; jjwt writes exp in seconds. |
| Spring property | jwt.expiration=900000 # ms, if your code does new Date(now + expiration) | Custom property: the unit is whatever your code assumes. Java Duration style: PT… |
| Spring Authorization Server | TokenSettings.builder().accessTokenTimeToLive(Duration.ofSeconds(900)) | Default access token: 5 minutes. |
| .NET | Expires = DateTime.UtcNow.AddSeconds(900) // TimeSpan 00:15:00 | Validation adds ClockSkew (default 5 minutes). |
| Go — golang-jwt v5 | "exp": jwt.NewNumericDate(time.Now().Add(900 * time.Second)) | NumericDate serializes to Unix seconds. |
| PHP — firebase/php-jwt | 'exp' => time() + 900 | time() returns seconds. |
Claim definitions come from RFC 7519; units and defaults from each library’s documentation and source code; provider lifetimes from official documentation. Every table on this page is generated by the same code as the calculator. Tokens are decoded only in your browser and signatures are not verified — use your JWT library to validate tokens before trusting them.
Need to inspect the raw segments? Use the Base64 decoder. Building developer tools or an internal auth dashboard? We build branded calculators for your product.
Get Custom Calculator for Your Business