๐ JWT Decoder, Decode JSON Web Tokens Online
By Shihab Mia ยท Updated 2026-08-04
This tool only decodes the token. It does not verify the signature, so never trust an unverified token's contents for authorization.
Paste a JWT above and press Decode.
This JWT decoder takes a JSON Web Token and shows you what is inside it. Paste the token and it splits on the dots, Base64URL-decodes the header and payload, and pretty-prints both as readable JSON. Timestamp claims like exp and iat are converted to human dates, and the signature is shown exactly as it appears. The decoding happens entirely in your browser, so the token you paste never leaves your device. One important note: this tool decodes but does not verify the signature, so it cannot tell you whether a token is genuine.
What is the JWT Decoder?
A JSON Web Token (JWT, usually pronounced "jot") is a compact, URL-safe way to carry a set of claims between two parties, most often used for authentication and authorization in web APIs. A signed JWT has three parts separated by dots: the header, the payload, and the signature. Each of the first two parts is a JSON object that has been Base64URL-encoded, and the third part is a cryptographic signature over the first two. Written out, a token looks like header.payload.signature. This three-part structure, formally called a JWS (JSON Web Signature) compact serialization, is what almost every "JWT" you see in the wild actually is.
The header usually states the signing algorithm (the "alg" field, such as HS256 or RS256) and the token type ("typ": "JWT"). It can also include a "kid" (key ID) that tells the verifier which key to use when several are in rotation. The payload holds the claims: statements about the user or the token itself. Some claim names are reserved and standardised, such as "sub" (subject), "iss" (issuer), "aud" (audience), "exp" (expiry), "iat" (issued at), and "nbf" (not before). The time-based claims are stored as Unix timestamps, that is the number of seconds since 1 January 1970 UTC, which this tool converts into readable dates so you can see at a glance when a token was issued or when it expires. Everything outside the reserved names is a private or public claim your application defines itself, such as roles, scopes, or a tenant id.
Decoding a JWT is not the same as verifying it. Anyone can read the header and payload because Base64URL is just an encoding, not encryption, so a JWT should never carry secrets like passwords or credit card numbers. The signature is what proves the token has not been tampered with and was issued by a party holding the signing key. Verifying it requires that key and the matching algorithm, which a client-side decoder does not have. That is why this tool deliberately shows the signature as-is without checking it: it is built for inspecting and debugging tokens, not for deciding whether to trust one. If you need actual verification, do it on the server with a JWT library and the real signing key, never in a browser tool.
JWTs come in two families that are easy to confuse. A JWS token, the kind this decoder handles, is signed but not encrypted, so its claims are always readable. A JWE (JSON Web Encryption) token has five dot-separated parts instead of three and its payload is actually encrypted, so it cannot be read without the decryption key. If your token splits into three parts on the dots, it is a standard signed JWT and this tool will decode it; if it splits into five, it is an encrypted JWE and no browser-side decoder can show you the payload.
Security researchers have repeatedly found that the weak point in JWT systems is rarely the token format itself, it is how servers verify it. Two well-documented attack classes are worth knowing even if you only ever decode tokens for debugging. The "alg: none" attack exploits libraries that treat an unsigned token as valid when the header says "alg": "none", letting an attacker edit the payload freely with no signature at all. Algorithm confusion attacks target servers that accept both RS256 and HS256: an attacker takes the server public key, which is often published openly, and uses it as the HMAC secret to forge a token that the server incorrectly verifies as authentic. Both problems are fixed the same way, by pinning the server-side verifier to a single expected algorithm and rejecting anything else, rather than trusting whatever alg value shows up in the token header.
Because a decoded JWT is just JSON, you can also inspect it by hand without any tool: split the string on the two dots, Base64URL-decode the first two segments (adding back = padding if your decoder needs it), and parse the result with any JSON parser. This decoder automates that process, adds date formatting for time claims, flags an expired exp, and gives you copy buttons for the header and payload, which is faster than writing a one-off script every time you need to check a token during development.
When to use it
- Debugging an API login flow by inspecting which claims your auth server actually puts in the token.
- Checking the exp claim to see whether a token has already expired and why a request is being rejected.
- Confirming the roles, scopes, or user id encoded in a token while building or testing a backend.
- Teaching or learning how JWTs are structured by seeing the header, payload, and signature pulled apart.
- Comparing an access token and a refresh token side by side to see how their claims and lifetimes differ.
- Reviewing a third-party OAuth or OpenID Connect id_token before wiring it into your own application.
How to use the JWT Decoder
- Copy the JWT from your network tab, cookie, Authorization header, or environment file.
- Paste it into the input box. You can press Decode or use the bundled sample token to try it out.
- Read the pretty-printed header and payload, and check the decoded iat, exp, and nbf dates.
- Use the Copy buttons to grab the header or payload JSON. Remember the signature is shown but not verified.
Formula & method
Worked examples
Decode the classic jwt.io sample token.
- Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- Split on the dots into three parts.
- Base64URL-decode part 1 to get the header JSON.
- Base64URL-decode part 2 to get the payload JSON.
Result: Header {"alg":"HS256","typ":"JWT"}, payload {"sub":"1234567890","name":"John Doe","iat":1516239022}
Turn the iat timestamp into a readable date.
- The payload above has "iat": 1516239022.
- iat is in Unix seconds, so multiply by 1000 for milliseconds: 1516239022000.
- new Date(1516239022000) gives the moment in time.
- Format it as UTC for a stable, timezone-independent reading.
Result: iat 1516239022 is Thu, 18 Jan 2018 01:30:22 GMT
Spot an expired token from its exp claim.
- Suppose the payload contains "exp": 1700000000.
- Convert: new Date(1700000000 * 1000) is Tue, 14 Nov 2023 22:13:20 GMT.
- Compare that to the current date and time.
- If now is later than the exp date, the token has expired.
Result: An exp of 1700000000 means the token expired on 14 Nov 2023
Tell a JWS (signed) token apart from a JWE (encrypted) token.
- Count the dot-separated segments in the string.
- Three segments (header.payload.signature) means a standard signed JWT, decodable as JSON.
- Five segments means a JWE, where the payload is encrypted and not readable without the decryption key.
Result: A token with 3 parts is a JWS you can decode here; a token with 5 parts is an encrypted JWE this tool cannot read
The three parts of a signed JWT
| Part | Contents | Encoding |
|---|---|---|
| Header | Algorithm (alg) and token type (typ) | Base64URL of JSON |
| Payload | Claims about the user and the token | Base64URL of JSON |
| Signature | Cryptographic proof over header and payload | Base64URL of raw bytes |
Common registered (reserved) JWT claims
| Claim | Name | Meaning |
|---|---|---|
| iss | Issuer | Who created and signed the token |
| sub | Subject | Who the token is about, often a user id |
| aud | Audience | Who the token is intended for |
| exp | Expiration time | Unix time after which the token is invalid |
| nbf | Not before | Unix time before which the token is not valid |
| iat | Issued at | Unix time the token was created |
| jti | JWT ID | A unique identifier for the token |
Common JWT signing algorithms
| alg value | Type | Typical use |
|---|---|---|
| HS256 | Symmetric (shared secret, HMAC-SHA256) | Server-to-server or single-backend apps that hold the one secret |
| RS256 | Asymmetric (RSA private/public key) | Multi-service systems where many services only need the public key to verify |
| ES256 | Asymmetric (ECDSA, elliptic curve) | Same use as RS256 but with shorter keys and signatures |
| PS256 | Asymmetric (RSA-PSS) | Stronger padding scheme, used by some newer identity providers |
| none | Unsigned | Should never appear in a production token; a decoder-only demonstration value |
Common mistakes to avoid
- Thinking a decoded token is a verified token. Decoding only reads the contents. It does not prove the token is genuine. Authorization decisions must verify the signature on the server with the correct key.
- Putting secrets in the payload. The payload is only Base64URL-encoded, which anyone can decode. Never store passwords, card numbers, or other secrets in a JWT, signed or not.
- Misreading the exp and iat values as milliseconds. JWT time claims are in seconds since the Unix epoch, not milliseconds. Multiply by 1000 before passing them to JavaScript Date, or the date lands in 1970.
- Assuming alg:none is safe. A header of "alg": "none" means the token is unsigned. Some libraries used to accept these by default, which let attackers forge tokens. Always reject none in production.
- Letting a server accept more than one algorithm. If a server verifies both RS256 and HS256 tokens, an attacker can sign a forged token with HS256 using the server public key as the secret. Pin verification to one expected algorithm.
- Confusing a JWT with an opaque session token. Not every string that looks random is a JWT. If it does not split into exactly three Base64URL segments on the dots, it is likely an opaque token or a JWE, and a JWT decoder cannot read it as JSON.
Glossary
- JWT
- JSON Web Token, a compact token format that carries signed claims as three Base64URL parts: header, payload, and signature.
- Claim
- A single statement inside the payload, such as a user id (sub) or an expiry time (exp).
- Base64URL
- A URL-safe variant of Base64 that uses - and _ instead of + and / and usually drops the = padding, used to encode the JWT parts.
- Signature
- A cryptographic value over the header and payload that proves the token has not been altered and came from the signing party.
- alg
- The header field naming the signing algorithm, for example HS256 (HMAC with SHA-256) or RS256 (RSA with SHA-256).
- Unix timestamp
- A point in time expressed as the number of seconds since 1 January 1970 UTC, used by the exp, iat, and nbf claims.
- JWS vs JWE
- A JWS is a signed token (3 parts, readable, this tool decodes it); a JWE is an encrypted token (5 parts, payload not readable without the decryption key).
- Bearer token
- A token sent in the Authorization header as "Bearer <token>", meaning whoever holds it can use it, which is why JWTs must be transmitted and stored carefully.
Frequently asked questions
What is a JWT decoder?
A JWT decoder splits a JSON Web Token on its dots and Base64URL-decodes the header and payload so you can read the JSON claims inside. This one also converts time claims like exp and iat to readable dates. It decodes but does not verify the signature.
Does this tool verify the JWT signature?
No. It only decodes and pretty-prints the header and payload and shows the signature as-is. Verifying a signature needs the secret or public key and the matching algorithm, which a browser tool does not have. Never trust an unverified token for authorization.
Is it safe to paste my token here?
The decoding runs entirely in your browser with JavaScript, so the token is never sent to any server. That said, a real JWT is a credential, so avoid pasting production tokens into any online tool and prefer test tokens when you can.
How do I read the exp date in a JWT?
The exp claim is a Unix timestamp in seconds. Multiply it by 1000 and pass it to a Date to get a calendar date and time. This decoder does that for you and flags whether the token has already expired.
Why does my token have three parts separated by dots?
A signed JWT is structured as header.payload.signature. The header and payload are Base64URL-encoded JSON, and the signature protects them. A token with a different number of parts is not a standard signed JWT.
Can anyone read the data inside a JWT?
Yes, for a standard signed JWT. The payload is only Base64URL-encoded, not encrypted, so anyone with the token can decode and read its claims. That is why you must never place secrets such as passwords in a JWT payload.
What is the difference between a JWT and a session cookie?
A traditional session cookie holds just an id, and the server looks up the session data in its own store on every request. A JWT carries the claims inside itself, so a server can verify and read it without a database lookup, at the cost of being harder to revoke before it expires.
Why does my JWT have five parts instead of three?
A five-part token is a JWE (JSON Web Encryption), not a signed JWS. Its payload is genuinely encrypted, not just Base64URL-encoded, so it cannot be decoded as JSON without the decryption key. This tool is built for the standard 3-part signed format.
Where should I store a JWT on the client, localStorage or a cookie?
There is a real tradeoff. localStorage is readable by any JavaScript on the page, so it is exposed to XSS. An HttpOnly, Secure, SameSite cookie is not readable by JavaScript but needs CSRF protection. Most current guidance favors HttpOnly cookies for session tokens.
Can I decode a JWT without an online tool?
Yes. Split the string on the two dots, Base64URL-decode the first two segments, and parse each as JSON. Most languages have a one-line way to do this, for example atob() in a browser console after replacing - and _ with + and / and restoring padding.