Skip to content

JWT Decoder

Decode JWT (JSON Web Token) in your browser and visualize the header, payload, and signature.iat / exp / nbf are automatically converted to human-readable dates.

100% Free No signup Browser-only 5 languages Dark mode

About the JWT structure

A JWT is a string consisting of header.payload.signature three parts joined with dots (.). The header and payload are Base64URL-encoded JSON, and the signature is generated using the algorithm specified in the header (e.g., HS256 / RS256).

Key claims: iss (issuer), sub (subject), aud (audience), exp (expiration), nbf (not before), iat (issued at), jti (JWT ID)

If something is broken or not displaying correctly, let us know via the contact form .

📖 Where people get stuck

Splits a JWT into its header, payload and signature and converts time claims such as exp and iat into readable dates. Everything runs in the browser, and the signature is not verified, since that needs a key. The point to take away is that being able to decode it means anyone can read its contentsa JWT payload is not encrypted; it is merely Base64URL encoded.

Case What happens What to do
Putting secrets into the payload Base64URL is an encoding, not encryption — as this page demonstrates, anyone without a key can read the contents. Yet the belief that a signature makes it safe is stubborn, and you see designs that put personal data, the internal permission structure, in-house identifiers, and sometimes an email address and a date of birth, all into the payload. A JWT sits in localStorage or a cookie, appears in logs, and sometimes travels in a URLtreating its contents as public information is the accurate stance. Put only an identifier in the payload and look the rest up on the server — a user id and a role name, not a name, an email address or an address. If you need encryption, JWE (JSON Web Encryption) is a separate specification for it, but first ask whether it needs to be in the JWT at all: usually what you need is who this is, and what they are can stay on the server. The test is simple — would you mind this value appearing in plain text in an access log? If not, it can go in; if you would, it cannot.
Trusting the contents after merely decoding Without verifying the signature, a JWT is just a string the user can rewrite at will. Code that decodes it, reads role: "admin" and uses that for authorisation accepts a token in which the attacker wrote that value themselves. Two failures are historically famous. One is the alg: "none" attack: rewrite the header algorithm to none, leave the signature empty, and some implementations accepted it without complaint. The other is confusing HS256 with RS256, where getting the verifier to use the public key as an HMAC secret lets an attacker forge a valid signature from public information alone. Always verify with the library verification function, and pin the permitted algorithms explicitlyjwt.verify(token, key, { algorithms: ["RS256"] }). Omit that argument and some implementations will trust the alg in the header, which is to let a value the attacker controls decide how verification happens. Never use a decode-only function — anything named like jwt.decode — for an authorisation decision: the names are similar enough to be confused, but it performs no verification and exists only for debugging output. Before writing the code, check which function in your library verifies and which merely decodes.
The token still works after logging out Being stateless is the design advantage of a JWT and simultaneously its greatest constraint. The server does not store the token, so there is no way to invalidate an individual one after issuing it. Logging out really means discarding the token on the client, and anyone who copied it can keep using it until it expires. For the same reason, revoking a permission leaves the old permission written into tokens already issued. That is why access for someone who has left can persist for an hour after you thought you had cut it off. Use a short expiry paired with a refresh token — an access token of about fifteen minutes, renewed with a refresh token that the server does track. With that arrangement, revoking the refresh token cuts access within fifteen minutes at most. If immediate revocation is a requirement, you need a blocklist — storing the ids of revoked tokens and checking against it during verificationbut that means holding state, which gives up part of the reason for using a JWT. That is the decision point: if you genuinely need immediate revocation, a session id with a server-side session is simpler and more reliable. JWTs suit authentication that spans multiple services, or where you want verification itself to be distributed.

The time claims are in seconds. exp, iat and nbf are all Unix seconds, and putting milliseconds in gives an expiry fifty thousand years out — an effectively permanent token. Because JavaScript Date.now() returns milliseconds, writing Date.now() + 3600000 and dropping it into exp is a very common mistake; the correct form is Math.floor(Date.now() / 1000) + 3600. If the decoded date lands far in the future, suspect exactly this — showing the claims as readable dates is precisely what lets you catch it by eye. Second, allow a leeway of a few tens of seconds when validating nbf and exp, to absorb clock skew between servers; the major libraries all have that option. Finally, an operational warning: do not paste a live production token into an online JWT decoderit is a credential, and if it lands in the logs of whatever server you pasted it into, someone else can impersonate you with it. This page runs entirely in your browser, but make a habit of confirming that in the Network tab of your developer tools.

📖 How to Use

  1. 1
    Copy your JWT
    Get the JWT string from your API response or Authorization header.
  2. 2
    Paste into the input
    Paste the JWT into the top textarea and decoding runs automatically.
  3. 3
    Inspect header & payload
    View algorithm (alg), issuer (iss), expiration (exp) and other claims visually.

❓ Frequently Asked Questions

What is a JWT?
A JWT (JSON Web Token) is an authentication token made of three Base64URL-encoded parts (header.payload.signature) joined with dots. Commonly used for API auth after login.
Can this tool verify the signature?
This tool is decode-only. Signature verification needs the secret (HS256) or public key (RS256/ES256) — use our JWT Signer tool or verify on your backend.
Is the JWT sent to any server?
No. All decoding happens in your browser via JavaScript — no network request is made.
What if exp is expired?
An expired JWT is invalid. Use the refresh token to get a new JWT, or re-login. Always validate exp on the client side too.
🐛 Found a bug or issue with this tool?

Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.

* Browser info (UA / screen / language / URL) is sent automatically to help reproduce the issue