JWT Decoder
Paste a JWT to decode its header and payload. This tool only decodes, it does not and will not verify the signature, for reasons explained below. Everything runs in your browser, so pasting a real token is safe.
The structure of a JWT
A JSON Web Token is three base64url-encoded segments joined by dots:
header.payload.signature
The header declares the signing algorithm and token type,
typically {"alg":"HS256","typ":"JWT"}.
The payload holds the claims, meaning the actual statements about the user or session.
The signature is computed over the first two segments using a secret or private key. It proves the token was issued by someone holding that key and has not been altered since.
Note that the segments are base64url, not standard Base64, which is why
JWTs contain - and _ but never +,
/, or =. See the
Base64 tool for the difference.
The payload is not secret
This is the single most important thing to understand about JWTs, and it causes real data leaks.
The payload is encoded, not encrypted. Anyone holding the token can read every claim in it, using this page or a single line of code. The signature prevents modification, it does not provide confidentiality.
Consequently, a JWT payload must never contain passwords, API keys, personal data beyond what the client already knows, internal system details, or anything else you would not display to the token holder.
What belongs in a payload: a user identifier, roles or scopes, issuer and audience, and timestamps. Anything sensitive stays server-side, referenced by the identifier.
Standard claims
| Claim | Name | Meaning |
|---|---|---|
iss | Issuer | Who issued the token |
sub | Subject | Who the token is about, usually a user ID |
aud | Audience | Which service the token is intended for |
exp | Expiration | Unix time after which the token is invalid |
nbf | Not before | Unix time before which the token is invalid |
iat | Issued at | Unix time the token was created |
jti | JWT ID | Unique token identifier, used for revocation lists |
The three timestamp claims are Unix seconds. This tool converts them to readable dates and flags whether the token has expired. For manual conversion, see the Unix timestamp converter.
Beyond these, applications add their own claims freely, such as
role, email, or scope.
Why this tool will not verify signatures
Verification requires the signing key: the shared secret for HMAC algorithms such as HS256, or the public key for RSA and ECDSA algorithms such as RS256 and ES256. The token itself never carries it.
A website offering to "verify" your token by asking for the secret is asking you to paste a production signing key into someone else's page. With that key, an attacker can forge tokens for any user of your system. It is one of the more dangerous habits in web development tooling, and it is why this page deliberately omits the feature.
Signature verification belongs on the server, in your authentication middleware, using a well-maintained library. This decoder exists for inspecting what a token says, which is the common debugging need.
Practical notes
The alg: none attack
Early JWT libraries accepted {"alg":"none"}, meaning an
unsigned token, and treated it as valid. An attacker could strip the
signature, set the algorithm to none, and craft arbitrary claims. Modern
libraries reject this, but it remains a reason to configure an explicit
expected algorithm rather than trusting the header.
Expiry and clock skew
A token is valid between nbf and exp. Because
server clocks drift slightly, most libraries permit a small tolerance,
typically 30 to 60 seconds. If tokens fail validation immediately after
issue, mismatched server clocks are the usual cause.
Revocation is the hard part
JWTs are self-contained, so a server can validate one without a database
lookup. The flip side is that a token cannot easily be revoked before it
expires. Common mitigations are short expiry times with refresh tokens, or a
denylist keyed on jti, which reintroduces the state that JWTs
were meant to avoid.
Where to store tokens in a browser
localStorage is convenient but readable by any script on the page, so an XSS vulnerability exposes the token. HttpOnly cookies are not script-readable but require CSRF protection. Neither is universally correct, the choice depends on your threat model.
Frequently asked questions
Why can this tool not verify the signature?
Verification needs the issuer's secret or public key, which the token does not contain. Any site asking you to paste a signing secret is asking for the key to forge tokens. Verify server-side instead.
What are exp, iat, and nbf?
Expiration, issued-at, and not-before timestamps, all in Unix seconds. This tool converts them to readable dates and indicates whether the token has expired.
Is a JWT encrypted?
No. A standard JWT is signed but not encrypted, so the payload is readable by anyone holding the token. Encrypted tokens exist as a separate standard called JWE, which is far less commonly used.
Can I edit a JWT payload?
You can change the encoded text, but the signature will no longer match and any correctly implemented server will reject it. That is precisely what the signature is for.
Why does my JWT contain hyphens and underscores?
Because JWTs use base64url encoding, which substitutes - and
_ for + and / so the token is safe in
URLs.
Is my token sent anywhere when I decode it here?
No. Decoding happens entirely in your browser. Nothing is transmitted, logged, or stored, which is what makes it safe to inspect a real production token.
Related tools
- Base64 encoder and decoder, for the underlying encoding
- Unix timestamp converter, for the exp and iat claims
- JSON formatter, to tidy a decoded payload
- All developer tools