JWT Decoder
Split a JWT apart and read its header and payload. When a login is failing, the cause is usually that exp has passed or that iss or aud does not match what the server expects, so simply looking at the claims solves half of these cases.
What you enter never leaves your device. Everything runs in your browser; nothing is sent or stored anywhere.
Three pieces separated by dots
A JWT is three segments joined by dots: header, payload, signature. The first two are JSON written in URL-safe Base64; the third is a signature over those two, made with a key. This page decodes only the first two and does not read the third. The header's alg says which kind of signature it is and kid which key was used; the payload carries the claims — sub, iss, aud, exp and so on.
Encoded, not encrypted
Base64 reverses without a key, so anyone holding the token can read what is inside. The signature guarantees that the content has not been altered; it hides nothing. That is why passwords and personal data must not go into the payload. If content really has to be hidden there is a separate standard, JWE — it has five segments and its second segment is not JSON, so it will not decode here.
Times are in seconds
exp, iat and nbf are seconds since 1970 — not milliseconds. If the issuing code writes milliseconds, the expiry lands tens of thousands of years in the future and the token effectively never expires. This page converts all three into this device's local time and flags exp when it has passed. Clocks on the issuing and verifying servers can also differ by a few seconds, which is why a freshly issued token is sometimes rejected as not yet valid.
Rejected even though it has not expired
If iss is not the issuer the verifier expects, or the service is missing from aud, the token is rejected even with a perfect signature. aud may be a single string or an array. When login works but a different API returns 401, this is usually the cause — the token was not issued for that API.
Where to look first when it will not decode
The token is read the moment you paste it. If a part could not be decoded, look around the token first: a Bearer prefix from a header, a token= from a cookie, quotes, or a line break in the middle are the usual causes. Leading and trailing whitespace is trimmed; anything else is treated as part of a segment and fails. A token with a single dot — two parts — is read as unsigned and decoded anyway.
The expiry mark uses this device's clock
Expiry is judged against this computer's time, not the server's, so on a device whose clock is off a live token can show as expired and the reverse. exp, iat and nbf appear in the time rows only when they are numbers — a quoted "1700000000" shows in the payload but is never resolved to a time, the trace of issuing code that broke the rules.
Frequently asked questions
Does it verify the signature?
No. Verifying requires a secret or a public key, and asking people to paste signing keys into a web page teaches a habit worth avoiding. This page only reads what is inside the token — verify the signature on your server.
Is it safe to paste a token here?
This page sends nothing to a server, so the token does not leave your browser. That said, a JWT is itself a credential, so a live production token is best not pasted anywhere.
Does it verify the signature?
No — it only decodes. Verifying needs the issuer's secret or public key, and putting that into a browser is a bad idea. What you see here is what the token contains; whether it is genuine is the server's job.
Is it safe to paste someone else's token?
The token never leaves your browser here. But note that a JWT payload is encoded, not encrypted — anyone holding the token can read it. Be careful when sharing or screenshotting your screen.
It says expired, but the server accepts the token.
Either the server does not check expiry, allows a few minutes of leeway, or this device's clock runs fast. The reverse — live here, rejected there — means the server's clock is ahead or nbf has not arrived. The server decides; this page only reads the token with this device's clock.
Does anything I paste get sent to a server?
No. Everything runs inside your browser and nothing is uploaded or stored. That is why you can use it on things you would not normally paste into a web page, like an internal config file or a production query. It also works with your network disconnected.