JWT Encoder / Decoder | HS256
encoding / jwt JWT Encoder / Decoder
Decode a JSON Web Token to inspect its header and claims, or encode one with the algorithm of your choice. Useful for debugging an authentication problem, checking what a token actually asserts, or confirming when it expires. Decoding happens in your browser, so tokens you paste here are never transmitted.
The three parts of a token
A JWT is three Base64url segments joined by dots: header.payload.signature. The dots are literal separators, which is why a token is safe to put in a URL or an Authorization header — there is no character in the encoding that needs escaping.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c| Segment | Encoding | Contents |
|---|---|---|
| Header | Base64url(JSON) | The signing algorithm in <code>alg</code>, the type in <code>typ</code>, and optionally a key identifier in <code>kid</code>. |
| Payload | Base64url(JSON) | The claims — who the token is about, who issued it, when it expires, and whatever else the issuer chose to assert. |
| Signature | Base64url(bytes) | A MAC or signature over <code>header.payload</code>, proving the token was issued by a holder of the key and has not been altered. |
Supported algorithms
The alg header names how the signature was produced. RFC 7518 defines the registry; the families below are the ones this tool implements.
| alg | Hash | Bits | Key type | Curve |
|---|---|---|---|---|
| HS256 | SHA-256 | 256 | Shared secret | — |
| HS384 | SHA-384 | 384 | Shared secret | — |
| HS512 | SHA-512 | 512 | Shared secret | — |
| RS256 | SHA-256 | 256 | Public / private pair | — |
| RS384 | SHA-384 | 384 | Public / private pair | — |
| RS512 | SHA-512 | 512 | Public / private pair | — |
| ES256 | SHA-256 | 256 | Public / private pair | P-256 |
| ES384 | SHA-384 | 384 | Public / private pair | P-384 |
| ES512 | SHA-512 | 512 | Public / private pair | P-521 |
| PS256 | SHA-256 | 256 | Public / private pair | — |
| PS384 | SHA-384 | 384 | Public / private pair | — |
| PS512 | SHA-512 | 512 | Public / private pair | — |
The three families differ in more than key type. HS uses HMAC, so signing and verifying need the same secret. RS uses RSASSA-PKCS1-v1_5, the older RSA scheme. PS uses RSASSA-PSS, which adds randomised salting and is the scheme RFC 8017 recommends for new designs. ES uses ECDSA over a named curve, producing signatures a fraction of the size of an RSA one at equivalent strength.
A signed token is not an encrypted one
This is the most important thing to understand about JWTs, and the source of a great many security incidents. The header and payload are Base64url encoded, not encrypted. Anyone holding the token can read every claim in it without the key — this tool does exactly that.
The signature does not provide secrecy. It provides integrity: it proves the token was issued by someone holding the signing key and has not been altered since. Those are different guarantees, and confusing them is how personal data ends up sitting readable inside a token.
The practical rule: never put anything in a payload that you would not be willing to show the token's bearer. No passwords, no secrets, no sensitive personal information.
Standard claims
The payload can carry anything, but the claim names registered in RFC 7519 §4.1 have agreed meanings and are what libraries validate automatically. All of them are optional — a token asserting nothing is still a valid JWT, which is why a verifier must check that the claims it depends on are actually present rather than assuming they are.
- iss (issuer)— who created the token.
- sub (subject)— who the token is about, typically a user ID.
- aud (audience)— who the token is intended for. A service should reject tokens not addressed to it.
- exp (expiration time)— after this moment the token must be rejected.
- nbf (not before)— the token is invalid until this time.
- iat (issued at)— when the token was created, useful for age policies.
- jti (JWT ID)— a unique identifier, used to prevent replay.
Time claims are Unix timestamps — seconds since 1 January 1970 — which is why they look like large integers rather than dates.
Claim reference
Every field this tool recognises, in both the header and the payload — the same dictionary that powers the hover tooltips in the header/payload editors above, so a claim documented here is a claim you can hover on screen to see this same summary.
| Claim | Name | Where | Registered | Meaning |
|---|---|---|---|---|
| alg | Algorithm | Header | RFC 7519 §4.1 | Names the algorithm family and hash — e.g. HS256 (HMAC-SHA256) or RS256 (RSA-SHA256). Attacker-controlled: a verifier must pin the algorithm it expects rather than trust this field, or it has asked the token how to check itself. See RFC 7518 §3.1 and RFC 8725 §3.1. |
| typ | Type | Header | RFC 7519 §4.1 | Optional and rarely meaningful in practice — nearly every JWT sets this to the literal string "JWT". Present mainly so a token can be told apart from other compact serialisations that share the same three-segment shape. |
| kid | Key ID | Header | RFC 7519 §4.1 | A hint for the verifier when the issuer rotates keys or publishes several at once (e.g. via a JWKS endpoint) — it says which entry in that key set to use, so the verifier does not have to try them all. |
| cty | Content Type | Header | RFC 7519 §4.1 | Almost never set. Only meaningful when the payload itself is another JWT (a "nested JWT", e.g. an encrypted token wrapping a signed one) — this tells the consumer that. |
| iss | Issuer | Payload | RFC 7519 §4.1 | A string or URI identifying the party that issued the token. A verifier that trusts more than one issuer should check this claim against an allow-list. |
| sub | Subject | Payload | RFC 7519 §4.1 | Identifies the principal the claims are asserting something about. Should be unique within the issuer, and stable — do not reuse a subject identifier for a different user later. |
| aud | Audience | Payload | RFC 7519 §4.1 | A string or array of strings naming the intended recipient(s). A service that receives a token should reject it if its own identifier is not listed here — otherwise a token minted for one service can be replayed against another. |
| exp | Expiration Time | Payload | RFC 7519 §4.1 | A Unix timestamp (seconds since 1970-01-01). The single most commonly checked claim — an expired token is the most common cause of an unexpected 401. A verifier must reject the token once the current time is at or after this value. |
| nbf | Not Before | Payload | RFC 7519 §4.1 | A Unix timestamp; the mirror image of `exp`. Used to issue a token that only becomes valid in the future — e.g. one distributed ahead of a scheduled access window. |
| iat | Issued At | Payload | RFC 7519 §4.1 | A Unix timestamp recording issuance time. Useful for age-based policies (e.g. "reject if older than 24 hours") independent of whether `exp` was also set. |
| jti | JWT ID | Payload | RFC 7519 §4.1 | A unique string, typically a UUID. Lets a verifier that keeps a short-lived blocklist detect and reject a token it has already seen once, even though it is still within its validity window. |
| name | Full name | Payload | No — private claim | Not registered in RFC 7519: an issuer is free to add claims like this one for its own purposes, as long as the name does not collide with a registered or public claim someone else relies on. Shown here because it appears in this tool's own example payload. |
Common uses
- Debugging authentication— see what claims a token actually carries when a request is rejected.
- Checking expiry— confirm whether a token has lapsed, the single most common cause of a sudden 401.
- Inspecting OAuth and OpenID tokens— identity providers issue JWTs, and reading them clarifies what a provider is asserting.
- API development— verify that the tokens your service issues contain the claims you intended.
- Confirming the algorithm— check that a token is signed with the algorithm you expect.
Security pitfalls
- The "none" algorithm.A token can claim it needs no signature. RFC 7518 registers
nonefor unsecured tokens, and libraries that honoured it in a verifying context allowed anyone to forge tokens freely. Always validate against an expected algorithm rather than trusting the header. - Trusting the header's algorithm choice.Related, and equally serious: an attacker who switches a token from RS256 to HS256 may be able to sign it with the RSA public key, because a verifier that follows the header will use that public key as an HMAC secret — and the public key is, by definition, known. Pin the algorithm on the server.
- Not verifying at all.Decoding is not validating. A token is only trustworthy once its signature has been checked against the correct key.
- Long or absent expiry.A leaked token stays valid until it expires, and JWTs cannot easily be revoked. Keep lifetimes short and use refresh tokens.
- Storing tokens carelessly.A token in browser storage is exposed to any script running on the page.
Frequently asked questions
Can anyone read my JWT?
What does the signature actually prove?
HMAC or RSA — which should I use?
Why is my token rejected even though it looks correct?
exp claim against the current time. After that, the usual causes are a mismatched audience, an algorithm the server does not accept, or clock skew between the issuing and verifying machines.How do I revoke a JWT?
Is my token sent anywhere by this tool?
Standards and references
- RFC 7519 JSON Web Token (JWT) 2015
- RFC 7515 JSON Web Signature (JWS) 2015
- RFC 7518 JSON Web Algorithms (JWA) 2015
- RFC 7517 JSON Web Key (JWK) 2015
- RFC 8725 JSON Web Token Best Current Practices 2020
- RFC 8017 PKCS #1: RSA Cryptography Specifications Version 2.2 2016