JWT Decoder & Verifier
Paste a JSON Web Token to read its header and claims, see when it expires, and check its signature. The token never leaves your browser.
—
—
| Claim | Value | Meaning |
|---|
Verify signature
alg: —How to use this JWT decoder
- Paste the token in the left box. You can paste the whole
Authorizationheader value: aBearerprefix, quotes and line breaks are removed for you. - Read the header and payload on the right. The Claims explained table says what each standard claim means and turns
exp,nbfandiatinto dates in your time zone, with "in 2 hours" or "3 days ago". - Check the status line: it says at once whether the token is expired, not valid yet, or still valid, and warns about risky headers such as
alg: none. - Verify the signature (optional): paste the HMAC secret, or the issuer's public key as PEM, X.509 certificate, JWK or a whole JWKS. The result updates as you type.
The token, secret and keys stay in this browser tab. Nothing is sent to a server, stored or logged. Signatures are checked with the browser's built-in Web Crypto API.
What is a JWT?
A JSON Web Token (JWT, said "jot", defined in RFC 7519) is a small, signed piece of JSON that a server gives to a client after login. The client sends it back with every request, usually in the header Authorization: Bearer <token>, and the API can check who the user is without a database lookup.
A JWT has three parts, separated by dots. Each part is Base64URL-encoded:
- Header (red):
{"alg":"HS256","typ":"JWT"}, the signing algorithm and the token type, sometimes a key idkid. - Payload (purple):
{"sub":"1234567890","name":"John Doe","iat":1516239022}, the claims about the user and the token. - Signature (green): made from
header.payloadwith a secret or private key. If one character of the header or payload changes, the signature no longer matches.
Encoded is not encrypted. Anyone who has the token can read the payload, as this page shows. The signature protects the token against changes, not against reading. Never put passwords, card numbers or other secrets in a JWT.
Standard JWT claims
| Claim | Name | What it means |
|---|---|---|
iss | Issuer | Who created and signed the token, for example https://accounts.google.com. |
sub | Subject | Who the token is about, usually the user id. |
aud | Audience | Which API or app the token is for. An API must reject tokens made for another audience. |
exp | Expiration time | After this moment the token must be rejected. Unix time in seconds. |
nbf | Not before | The token must not be accepted before this moment. |
iat | Issued at | When the token was made. Useful to see how old it is. |
jti | JWT ID | A unique id for this token, used to block replays or revoke one token. |
OpenID Connect ID tokens add claims such as email, name, nonce, auth_time and azp; OAuth access tokens often carry scope or roles. The time claims are Unix timestamps; you can also convert them with the Unix timestamp converter.
JWT signing algorithms
| alg | Type | Signs with | Verifies with |
|---|---|---|---|
HS256 HS384 HS512 | HMAC + SHA-2 | Shared secret | The same secret |
RS256 RS384 RS512 | RSA PKCS#1 v1.5 | RSA private key | RSA public key |
PS256 PS384 PS512 | RSA-PSS | RSA private key | RSA public key |
ES256 ES384 ES512 | ECDSA (P-256, P-384, P-521) | EC private key | EC public key |
EdDSA | Ed25519 | Ed25519 private key | Ed25519 public key |
none | No signature | — | Nothing. Servers must reject it. |
Use HS256 when one service both creates and checks tokens. Use RS256 or ES256 when other services must verify tokens without being able to create them: they only get the public key, usually from a JWKS URL. Need a key pair to test with? The RSA key generator makes one in the browser.
JWT security checklist
- Always verify the signature on the server before you trust any claim. Decoding alone proves nothing.
- Fix the algorithm in your code (for example only
RS256) instead of trusting thealgin the header, and rejectnone. - Check
exp,nbf,issandaud. Allow at most a minute or two of clock difference. - Keep access tokens short-lived (minutes, not weeks) and use refresh tokens to get new ones.
- Use a long random secret for HS256: at least 32 random bytes. Short or guessable secrets can be cracked offline from a single token.
- Treat tokens like passwords: do not log them, do not put them in URLs, and do not paste live production tokens into chats or tickets.
Decode and verify a JWT in code
| Language | Read the payload (no check) | Verify |
|---|---|---|
| JavaScript (browser) | JSON.parse(atob(t.split('.')[1].replace(/-/g,'+').replace(/_/g,'/'))) | Do it on the server |
| Node.js | JSON.parse(Buffer.from(t.split('.')[1], 'base64url')) | jwt.verify(t, key, { algorithms: ['RS256'] }) (jsonwebtoken) |
| Python | jwt.decode(t, options={"verify_signature": False}) | jwt.decode(t, key, algorithms=["RS256"], audience="my-api") (PyJWT) |
| Java | JWT.decode(t).getClaims() | JWT.require(Algorithm.HMAC256(secret)).build().verify(t) (java-jwt) |
| C# | new JwtSecurityTokenHandler().ReadJwtToken(t).Claims | handler.ValidateToken(t, parameters, out _) |
| Go | jwt.NewParser().ParseUnverified(t, jwt.MapClaims{}) | jwt.Parse(t, keyFunc, jwt.WithValidMethods([]string{"RS256"})) (golang-jwt) |
The browser line uses atob(), which breaks on non-ASCII text such as accented names; the Base64 tool explains the UTF-8-safe way.
Frequently asked questions
Is it safe to paste my JWT into this decoder?
Yes. Decoding and signature checks run in your browser with JavaScript and the Web Crypto API. The token, secret and keys are not uploaded, logged or stored. Still, a valid token works like a password until it expires, so do not share real production tokens in chats, tickets or screenshots.
Is a JWT encrypted?
Usually not. A normal JWT (JWS) is only Base64URL-encoded and signed: anyone who has the token can read the header and payload, as this page shows. The signature only proves who made the token and that nobody changed it. Never put passwords or other secrets in a JWT payload. Encrypted tokens (JWE) have five parts instead of three.
Why does my token show as expired?
The exp claim is the expiry time in seconds since 1 January 1970 UTC. If exp is earlier than the current time, servers reject the token and the client must get a new one, usually with a refresh token. If a token looks expired in the year 1970 or valid until the year 50000, the issuer probably wrote milliseconds instead of seconds; this tool warns about that.
What is the difference between HS256 and RS256?
HS256 signs with one shared secret: the same secret creates and checks the signature, so every service that verifies tokens can also create them. RS256 signs with an RSA private key and is checked with the public key, so many services can verify tokens while only the issuer can make them. ES256 works like RS256 with a smaller elliptic-curve key.
Where do I find the public key to verify a token?
Identity providers publish their public keys as a JWKS (JSON Web Key Set), usually at /.well-known/jwks.json, or at the jwks_uri listed in /.well-known/openid-configuration. Paste the whole JWKS here: the tool picks the key whose kid matches the token header. A PEM public key (BEGIN PUBLIC KEY or BEGIN RSA PUBLIC KEY) or an X.509 certificate (BEGIN CERTIFICATE) also works.
Can I change the payload of a JWT?
You can edit and re-encode the payload, but the signature then no longer matches, and a correct server rejects the token. Only someone with the secret or private key can make a valid signature. That is the whole point of signing, and it is why servers must always verify the signature and must not accept alg none.
What do iat, nbf, exp, sub, iss and aud mean?
They are registered claims from RFC 7519. iat is when the token was issued, nbf is the time before which it must not be accepted, and exp is when it expires (all in Unix seconds). sub is the subject, usually the user id. iss is the issuer that created the token, and aud is the audience: the API or app the token is meant for. jti is a unique token id.