- Does this verify the signature?
- No, on purpose. Verifying a JWT signature requires the secret (for HMAC tokens) or the public key (for RSA/ECDSA). Asking for that in a paste-and-read web tool is exactly how secrets leak — somebody pastes a production secret into the wrong tab and now it's in browser history, error logs, autocomplete. This decoder reads the public parts of the token and stops there. For verification, use the JWT library that's already in your server: jose for Node, PyJWT for Python, jjwt for Java, golang-jwt for Go.
- What's a JWT, in one paragraph?
- A JSON Web Token is three base64url-encoded chunks joined by dots: header.payload.signature. The header is JSON like {"alg":"HS256","typ":"JWT"}. The payload is JSON with claims like {"sub":"user_123","exp":1735689600}. The signature is a hash of header+payload computed with a secret, so a server with the same secret can verify the token wasn't tampered with. The point: a server can hand you a token, you carry it on every request, and the server doesn't need a session database to trust you — verifying the signature is enough.
- How is this different from jwt.io?
- jwt.io is the reference and it's excellent. We do less on purpose — no signature verification, no signing — which means we never ask you to paste a secret, period. That's the trade. If you want to verify, use jwt.io or your server library. If you just want to see what's inside a token, this loads faster, has no ads, and doesn't pitch you Auth0 in the sidebar.
- What are exp, nbf, iat, sub, iss, aud, jti?
- The seven standard claims defined in RFC 7519. exp is the expiration time (Unix seconds — the token stops being valid after this). nbf is 'not before' (Unix seconds — the token isn't valid before this). iat is 'issued at' (Unix seconds — when the server minted the token). sub is the subject (usually a user ID). iss is the issuer (which service minted it). aud is the audience (which service is supposed to accept it). jti is a unique token ID (used for revocation lists). All seven are optional — most real tokens use sub, iat, exp, and sometimes iss/aud.
- Why does the timestamp show a date thousands of years away?
- JWT timestamps are in seconds since 1970-01-01 UTC, not milliseconds. If you see a date in the year 50,000+, someone passed a JavaScript Date.now() millisecond value into a JWT claim by mistake. The token will work in most libraries (they read whatever number they find) but will never expire. Re-mint with Math.floor(Date.now() / 1000).
- The header says alg: none — is that bad?
- It's the famous attack. Some JWT libraries from 2014-2016 accepted a token with alg: none and skipped signature verification entirely, meaning an attacker could forge any payload. Modern libraries refuse alg: none by default. If you see it in a real token, treat it as broken — either a misconfigured library on the issuing side or someone testing an attack. Production tokens should use HS256 or RS256.
- Can I decode RSA-signed (RS256/ES256) tokens here?
- Yes. Decoding doesn't care about the algorithm — it just base64url-decodes the parts and shows them. The algorithm only matters for verification (which this tool doesn't do). RS256 and ES256 tokens look identical to HS256 tokens in shape; only the signature bytes differ.
- Is the token stored or sent anywhere?
- No. The page is a static HTML file with a small bit of JavaScript. The JavaScript runs in your browser, does the decoding, and shows the result. There's no fetch, no localStorage, no analytics on the token contents. Close the tab and the token is gone. We don't even know you decoded one.