JWT Decoder
Paste a JWT to see its header and payload as formatted JSON, check when it expires and verify HS256, HS384 or HS512 signatures.
Registered claims
| sub · Subject | 1234567890 |
| exp · Expires | 1793178000 |
| iat · Issued at | 1793174400 |
ztool-demo-secret. 🔒 Runs entirely in your browser. Nothing you enter is sent to a server.
JSON Web Tokens (JWTs) carry identity and permission data between servers, browsers and APIs. They look like a long string of random characters, but most of a JWT is just encoded JSON that anyone can read. This JWT decoder turns a token back into readable JSON, explains the standard claims, shows when it expires and can check an HMAC signature if you know the secret.
How to use the JWT decoder
- Paste a token into the box. A leading
Bearerfrom an Authorization header is removed for you. - Read the header and payload, formatted as JSON.
- Check the registered claims table. Times such as
expandiatare converted to dates. - To check the signature of an HS256, HS384 or HS512 token, type the secret into the verify box.
The example token already in the box was signed with the secret ztool-demo-secret. Try it, then change one character of the token and watch the verification fail.
How a JWT is structured
A signed JWT has three parts separated by dots:
header.payload.signature
- Header: JSON that names the signing algorithm, for example
{"alg":"HS256","typ":"JWT"}. - Payload: JSON with the claims, the statements about the user and the token.
- Signature: proof that the first two parts were created by someone with the key.
The header and payload are encoded with Base64url, a version of Base64 that uses - and _ instead of + and / and drops the = padding, so tokens are safe in URLs. Encoding is not encryption, so never put secrets in a payload.
For HMAC algorithms the signature is:
signature = Base64url( HMAC-SHA256( secret, header + "." + payload ) )
Worked example
Take the example token. Its first part, eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9, decodes to:
{"alg":"HS256","typ":"JWT"}
The second part decodes to a payload containing "sub":"1234567890", a name, a role, "iat":1793174400 and "exp":1793178000.
iat1793174400 is 28 October 2026, 08:00:00 UTC, when the token was issued.exp1793178000 is exactly 3,600 seconds later, 09:00:00 UTC, so the token was valid for one hour.
Computing HMAC-SHA256 over the first two parts with the key ztool-demo-secret gives exactly the third part, which is why the signature verifies.
The registered claims
| Claim | Name | Meaning |
|---|---|---|
iss |
Issuer | Who created the token, such as your login server |
sub |
Subject | Who the token is about, usually a user ID |
aud |
Audience | Which service the token is meant for |
exp |
Expiration time | After this moment the token must be rejected |
nbf |
Not before | Before this moment the token must be rejected |
iat |
Issued at | When the token was created |
jti |
JWT ID | A unique ID, useful for blocking reuse |
Everything else in the payload, such as name or role, is a custom claim defined by the application.
Debugging common JWT problems
- “Token expired” errors. Compare
expwith the current time. Server clocks that are a few minutes apart can also cause early rejection, which is why many libraries allow a little clock skew. - “Invalid signature” errors. The secret or key is wrong, the token was cut off when copied, or the token was signed with a different algorithm than the server expects.
- “Invalid audience” errors. The
audclaim does not match the value your API is configured to accept. - Missing claims. If a role or permission is not in the payload, the identity provider is not adding it. Check its token configuration.
Security tips
- Always verify on the server. Never trust a decoded payload until its signature has been checked with the right key.
- Reject
"alg": "none". Unsigned tokens must never be accepted. - Keep tokens short-lived. Short expiry times limit the damage if a token leaks. Use refresh tokens for longer sessions.
- Use long random secrets for HMAC. At least 32 random bytes for HS256. A short, guessable secret can be found by brute force from a single token.
- Do not store sensitive data in the payload. Anyone holding the token can read it.
Frequently asked questions
Is it safe to paste a token here?
The token is decoded in your browser and never sent to a server. Still, treat live tokens like passwords. Anyone who has a valid token can usually use it until it expires, so avoid pasting production tokens into tools you do not trust.
Does decoding a JWT verify it?
No. Decoding only reads the contents, which anyone can do because the header and payload are just Base64url-encoded. Verification checks the signature with the secret or public key, and your server must always do that before trusting a token.
Can I verify RS256 or ES256 tokens?
Not in this tool. It verifies HMAC tokens (HS256, HS384 and HS512) when you enter the shared secret. RS256 and ES256 tokens need the issuer's public key, usually published at a JWKS endpoint.
Why does the tool say my token has 5 parts?
A token with five parts is an encrypted JWT (JWE) rather than a signed one (JWS). Its payload is encrypted, so it cannot be read without the decryption key.
What time zone are the exp and iat dates in?
JWT times are Unix timestamps, counted in seconds since 1 January 1970 UTC. The tool shows them in UTC, along with how long ago or how far in the future they are.