How to use it
Paste a token into the JSON Web Token box, or press a sample: Signed token, Expired token or alg: none. It’s decoded as you type, in the page; nothing is sent anywhere. A leading Bearer and any spaces or line breaks are removed first, so an Authorization header value can go in as it is.
- The status line checks the token against your device’s clock: valid, expired or not valid yet, and by how much.
- The three parts shows the header, payload and signature, each in its own color. Any warnings follow, such as a missing signature.
- A sentence names the header’s
algand who holds the key behind it. - header and payload show the decoded JSON.
- Claims explains each standard claim the token carries, and shows a time claim’s instant as an ISO 8601 timestamp in UTC.
If the text isn’t a JWT, one sentence names the part that failed and why.
Examples
An access token copied from an Authorization header, checked at 2026-10-14T09:40:00Z:
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20iLCJzdWIiOiJ1c2VyXzgyMzEiLCJhdWQiOlsiYXBpLmV4YW1wbGUuY29tIiwiYmlsbGluZy5leGFtcGxlLmNvbSJdLCJpYXQiOjE3OTE5Njg0MDAsImV4cCI6MTc5MTk3MjAwMCwic2NvcGUiOiJyZWFkOmludm9pY2VzIn0.1nm_H3GpNBYSDrust9L2urWuNx3Gwn_lXf1-GASBIsg
The status line reads Valid now: it expires in 20 minutes. and Claims shows:
iss https://auth.example.com
sub user_8231
aud api.example.com, billing.example.com
iat 1791968400 2026-10-14T09:00:00.000Z
exp 1791972000 2026-10-14T10:00:00.000Z
The token’s scope is only in the payload JSON: Claims covers iss, sub, aud, iat, nbf and exp.
The same session with its times taken from Date.now(), which counts milliseconds, at the same moment:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzgyMzEiLCJpYXQiOjE3OTE5Njg0MDAwMDAsImV4cCI6MTc5MTk3MjAwMDAwMH0.8qRjoKxJCdR9yqmoudHUZ-Zxv6x2oLOxZVPgwoRzOag
iat 1791968400000 +058755-03-22T00:00:00.000Z
exp 1791972000000 +058755-05-02T16:00:00.000Z
The status line reads Valid now: it expires in 56766 years. JWT times are seconds, so an exp check will pass for the next 56,766 years.
A payload encoded with standard Base64 instead of base64url:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyXzgyMzEiLCJuYW1lIjoiWm/DqyIsImV4cCI6MTc5MTk3MjAwMH0=.1nm_H3GpNBYSDrust9L2urWuNx3Gwn_lXf1-GASBIsg
The error is The payload isn't base64url: "/" isn't one of its characters (A-Z, a-z, 0-9, "-", "_"). Swap the / for _ and the token decodes, trailing = and all.
Good to know
- Decoding isn’t verifying. Nothing here checks the signature, and anyone can make a token that decodes to any claims. The payload isn’t encrypted either, so keep secrets out of it.
- A JWT is three base64url parts (RFC 7519, in the JWS compact form of RFC 7515). Base64url is RFC 4648’s URL-safe alphabet, with
-and_for+and/, and JWTs drop the=padding; this tool accepts it either way. - Five parts means an encrypted JWE (RFC 7516), whose payload can’t be read without the key. It fails here with
A JWT is three base64url parts separated by dots, and this one has 5. - Times are NumericDate: seconds since 1970-01-01T00:00:00Z. An
expwritten as the string"1767225600"isn’t one and gets the warningThe "exp" claim isn't a number of seconds, so its time can't be read. - There’s no grace period. Per RFC 7519 a token is expired from the second its
exparrives and not valid beforenbf. The RFC lets servers allow a few minutes for clock skew, so a server may accept a token this page just called expired. - The status rounds down, with 365-day years: the Expired token sample, 651 days past its
exp, readsExpired 1 year ago. HS256uses one shared secret to sign and verify, so whoever can check the token can forge one.RS,PS,ESandEdDSAsign with a private key and verify with the public one.alg: nonemeans no signature and gets a warning. RFC 8725 (JWT best practices) has verifiers accept only the algorithms they expect, which blocksnoneand passing an RSA public key off as an HMAC secret.- Paste from
Beareron, not the wholeAuthorization:line, whose colon fails. Tokens are limited to 8,000 characters.
Questions
How do I check if a JWT is expired?
Paste it here: the status line compares exp with your clock. In code, it’s expired once Date.now() >= payload.exp * 1000, since exp is in seconds and Date.now() in milliseconds.
Can I decode a JWT without the secret key?
Yes: the header and payload are only base64url-encoded. The secret, or the public key for RS256 and its kin, is needed only to verify the signature. In Node’s jsonwebtoken, jwt.decode() reads a token and jwt.verify() checks it.
Is it safe to decode a JWT online?
On this page, yes: the token is decoded in your browser and never sent anywhere. An unexpired token works like a password, so don’t paste one into a site that sends it to a server.
How do I decode a JWT in code?
Base64url-decode the middle part and parse the JSON. In Node: JSON.parse(Buffer.from(token.split('.')[1], 'base64url')). Python’s base64.urlsafe_b64decode needs the padding back first: append '=' * (-len(part) % 4).