Just File Tools

JWT Decoder

Decode and inspect JSON Web Tokens (header, payload, signature)

This tool decodes only — it does not verify signatures. Anyone with the base64-url decoding spec can read your JWT contents, so never put secrets in the payload. Never trust a decoded payload server-side without verifying the signature against your secret key.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MzAwMDAwMDB9.RAW_BYTES_NOT_VERIFIED
Algorithm:HS256
Expires: 2024-10-27T03:33:20.000ZEXPIRED
Issued at: 2023-11-14T22:13:20.000Z
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "sub": "1234567890",
  "name": "Jane Doe",
  "iat": 1700000000,
  "exp": 1730000000
}
Signature (raw base64url, NOT verified)
RAW_BYTES_NOT_VERIFIED

How to JWT Decoder Online

Decode a JSON Web Token to inspect its header, payload, and signature segments.

  1. Paste your JWT into the input. A leading `Bearer ` (from an HTTP Authorization header) is automatically stripped.
  2. Watch the colored segments — red is the header, purple is the payload, sky-blue is the signature.
  3. The header panel shows the JSON header object, including the signing algorithm (`alg`).
  4. The payload panel shows the JSON claims. Look for `sub` (subject), `iss` (issuer), `aud` (audience), and the expiry timestamps.
  5. If the token has an `exp` claim, the tool tags it as `EXPIRED` or `valid window` based on the current time.
  6. If the algorithm is `"none"`, a red warning appears — historically a common source of authentication bypass bugs.
  7. Use the Copy buttons to grab the JSON of any segment for further inspection or to paste into your server-side debugger.

About JWT Decoder

A JSON Web Token (JWT, "jot") is the most-deployed authentication token format on the modern web. OAuth providers issue them, your identity provider returns them after login, and your backend trusts them to identify the user on subsequent requests. The format itself is dead simple: three pieces of data — a header, a payload, and a signature — each base64url-encoded and joined with dots. You can paste any JWT into this tool and see exactly what each piece contains. There is no magic.

The **header** is a JSON object describing how the token is signed. The two fields you will see in 99% of tokens are `alg` (the signing algorithm — usually `HS256` for HMAC-SHA256, `RS256` for RSA-SHA256, or `ES256` for ECDSA-SHA256) and `typ` (almost always `"JWT"`). For tokens signed by a third party like Auth0 or AWS Cognito, you may also see a `kid` (key ID) telling the verifier which public key to use from the issuer's JWKS endpoint.

The **payload** contains the claims — the actual statements the token makes. Standard claims defined in RFC 7519 include `iss` (issuer), `sub` (subject — usually the user ID), `aud` (audience — who the token is for), `exp` (expiration time), `iat` (issued at), and `nbf` (not before). Beyond those, applications stuff anything they want into the payload: email, role, tenant ID, feature flags. The decoder flags expired tokens with a red badge so you can immediately tell whether the token would still pass validation.

The **signature** is the part that makes JWT a trust mechanism. The issuer computes `HMAC(secret, header + "." + payload)` (for HS algorithms) or `SIGN(privateKey, header + "." + payload)` (for RS/ES algorithms) and appends the result. To verify, the receiver re-runs the same computation and compares. **This tool does not perform that verification** and cannot — it would require your secret key (for HMAC) or the issuer's public key (for asymmetric). Verification has to live in your server-side code, alongside the secret. Decoding without verifying is fine for *inspection*; trusting decoded contents without verifying is the bug.

One historical hazard worth knowing: the `alg: "none"` value. The spec allows tokens to declare they have no signature, and several popular JWT libraries shipped with the default behavior of accepting these as valid. An attacker could forge any payload, set `alg: "none"`, send an empty signature, and have the token accepted. Every modern library rejects `alg: none` by default, but the tester still flags it because legacy systems exist and review code occasionally accepts user-controlled `alg` values. **Never let the token's own `alg` field decide your verification algorithm.** Pin the algorithm in your verification code.

Another perennial confusion: **JWTs are encoded, not encrypted.** Base64url is reversible by anyone — that is exactly what this tool demonstrates. Do not put secrets in JWT payloads. Email addresses, role names, and tenant IDs are fine because they are not confidential to the holder of the token. API keys, internal IDs you do not want enumerated, or anything you would not show the user are not fine. If you need confidential claims, use **JWE** (JSON Web Encryption), which has five dot-separated segments and is genuinely encrypted. The overwhelming majority of "JWT" in the wild is JWS (signed) and shows the structure decoded by this tool.

All decoding happens in your browser. The token is split, each segment is base64url-decoded with the browser's native `atob`, and the JSON is parsed with `JSON.parse`. UTF-8 in the payload is handled via `TextDecoder` so emoji, accented letters, and CJK content round-trip cleanly. The pure-logic helper is around 1 KB compressed. Nothing about the token is logged, transmitted, or persisted.

Frequently Asked Questions

Does this verify the signature?

No, and it cannot — JWT signatures are verified using a key the issuer keeps secret. The whole point of the signature is that only the issuer (or anyone with the secret/public key) can compute or check it. A pure-browser tool has no access to your keys and should never have them, so this tool decodes only. To verify, run the token through your server-side library with the secret/JWKS endpoint that issued it.

Is decoding a JWT a security risk?

Reading a JWT is not a security risk — anyone with the token can already read it. JWTs are encoded, not encrypted (assume base64url ≈ plaintext). The risk is using the payload contents without verifying the signature. If your backend reads `payload.sub` to identify a user without verifying the signature, an attacker can forge any payload they want. The signature verification step is non-negotiable.

What is the `alg: "none"` warning about?

JWTs allow an `alg` value of `"none"`, which means "no signature, just trust me." Several major auth libraries shipped with bugs where they accepted `alg: none` tokens as valid, allowing attackers to forge any user identity by crafting a token with an empty signature. Modern libraries reject `alg: none` by default; the tester flags it so you know to make absolutely sure your verification path does too.

Why is the payload not encrypted?

Because JWT is a signing format, not an encryption format. The signing standard is JWS (JSON Web Signature); the encryption sibling is JWE (JSON Web Encryption), which has a different structure (five dot-separated segments instead of three). The vast majority of JWTs you encounter are JWS — encoded, signed, but readable by anyone. If you need confidential claims, use JWE or, more commonly, an opaque session token that maps to server-side state.

Why is my JWT showing weird characters in the payload?

JWT payloads are JSON encoded as UTF-8 then base64url-encoded. The decoder explicitly uses `TextDecoder('utf-8')` so emoji, accented letters, and CJK characters round-trip correctly. If you see mojibake (turkish 'i' becomes question marks, etc.), the issuer probably double-encoded the payload before signing — that is a server-side bug, not a decoder bug.

What is the difference between `iat`, `exp`, and `nbf`?

`iat` (Issued At) is when the token was created. `exp` (Expiration) is when it stops being valid. `nbf` (Not Before) is when it starts being valid — used for tokens that should not be honored until a future moment. All three are Unix timestamps (seconds since epoch). The decoder converts them to readable ISO dates and flags expired tokens with a red badge.

Is my token sent to a server?

No. Decoding happens entirely in your browser using `atob` and `JSON.parse`. The token never leaves your tab. Verify in your browser DevTools network panel.