JWT Decoder — Free Online Tool on Toolpile
Every tool you need, one place
PDF, Image, AI, Dev, and Business tools — free, private, no signup.
Toolpile uses cookies for analytics and ads. The tools themselves keep your files in the browser — that doesn't change. Read the full policy
PDF, Image, AI, Dev, and Business tools — free, private, no signup.
About JWT Decoder
A JWT (JSON Web Token) looks like an opaque blob until you see what's actually inside — three Base64URL chunks, separated by dots, holding a header, a payload, and a signature. Decoding reveals the contents in plaintext (yes, anyone can read them). Verifying takes a key. This tool decodes; what follows is when each part matters and what people most often get wrong about token security.
A JWT is three Base64URL-encoded JSON objects joined by `.` characters: `header.payload.signature`. Decode each part separately. The **header** says how the token is signed (`alg: HS256` for HMAC-SHA256, `RS256` for RSA, `ES256` for ECDSA, etc.) and what type it is (`typ: JWT`). The **payload** holds the actual data — the `claims` — which can be anything but conventionally include `sub` (subject, usually a user ID), `iat` (issued at, Unix timestamp), `exp` (expires at, Unix timestamp), `iss` (issuer), `aud` (audience). The **signature** is computed over the first two parts using the secret/private key — verifying it proves the token wasn't tampered with.
The single most-misunderstood thing about JWTs: **the payload is not encrypted**. Anyone can Base64-decode it. Putting passwords, credit cards, or anything sensitive in a JWT payload is a leak — assume every party that touches the token can read everything inside. The signature only proves the token came from someone with the secret key; it doesn't hide the contents. If you need encryption, use JWE (JSON Web Encryption) which is a different format, or encrypt sensitive fields before placing them in the JWT.
JWTs are designed for **short-lived authentication**: the issuer signs a token saying "this user is authenticated until time X", the receiver verifies the signature without contacting the issuer, the user re-authenticates after X. Long-lived JWTs (multi-day, multi-month) defeat the design — once issued, you can't revoke a JWT short of maintaining a server-side blocklist (which gives back the round-trip you saved by using JWT). The 2026 norm: 5-15 minute access tokens + a separate revocable refresh token in a server-side store.
RFC 7519 defines seven "registered claims" that have specific meanings — most JWT libraries enforce them automatically:
The most famous JWT vulnerability is **alg=none**. The original spec allowed `alg: none` (no signature) for some use cases. Many JWT libraries in 2015-2017 verified the signature using whatever algorithm the token claimed in its own header — so an attacker could change `alg` from `RS256` to `none`, blank out the signature, and the library would accept the token as valid. Fixed in modern libraries by requiring the verifier to specify accepted algorithms upfront, but old code (and some custom implementations) still has this bug.
**alg=HS256 with the public key as the secret**: another classic. If the verifier trusts the `alg` field, an attacker can change a token from `RS256` (asymmetric, server has private key) to `HS256` (symmetric, expects a shared secret) and sign the new token using the issuer's public key as the HMAC secret. The verifier, accepting `alg` from the header, validates with the public key — and it passes. Fix: never let the `alg` from the token header decide which key to use; the verifier must hard-code or look up the algorithm separately.
**Hardcoded weak secrets**: developers picking `secret`, `password`, or short strings as the HMAC key. Token cracking tools like `jwt-cracker` and `hashcat` can brute-force common HMAC secrets in minutes if exposed tokens are available. For HS256, use ≥32 bytes of random data — produced by a CSPRNG, not typed by hand.
**Storing tokens insecurely client-side**: putting JWTs in localStorage means any XSS vulnerability leaks every user's session. Putting them in `httpOnly` cookies means JS can't read them but also can't easily attach them to fetch calls without extra setup. The 2026 best practice is a combination — short-lived access token in memory (never persisted), refresh token in `httpOnly` SameSite=Strict cookie, refresh on demand.
Is decoding a JWT the same as verifying it?
No — and conflating them is dangerous. Decoding is reversible Base64URL — anyone can see the contents. Verification requires the signing key (HMAC secret for HS256, public key for RS256/ES256) and proves the token came from someone with the matching key. A decoded-but-not-verified JWT is just JSON someone sent you; trust nothing in it until verified.
Are JWTs encrypted?
JWTs as commonly used (JWS — JSON Web Signature) are signed but not encrypted. The payload is plaintext (Base64-encoded). For encryption, the spec defines JWE (JSON Web Encryption), which is a different format — it has 5 dot-separated parts instead of 3 and the payload is opaque ciphertext. Most production systems use JWS over HTTPS for confidentiality in transit and never persist tokens unencrypted.
Where should I store JWTs in a browser?
For SPAs in 2026: access tokens in memory (a JS variable, not localStorage — XSS risk). Refresh tokens in `httpOnly`, `SameSite=Strict`, `Secure` cookies — JS can't read them, the browser sends them automatically on same-site requests, no XSS leak. The flow: app loads → calls /refresh → gets new access token → uses it → repeats every 15 min. Avoid putting JWTs in localStorage even though it's the path-of-least-resistance — every XSS vuln becomes a session hijack.
How long should a JWT live?
Access tokens: 5-15 minutes is the modern norm. Long enough that you don't refresh on every request; short enough that a stolen token has limited damage. Refresh tokens: hours to days, but stored server-side as well so they can be revoked when a user signs out or you detect compromise. Never issue a JWT without `exp` — even week-long tokens are safer than non-expiring ones.
Why does my JWT look like garbage when I just see eyJ...?
It is garbage to read directly — Base64URL-encoded JSON. The `eyJ` prefix is the Base64URL of `{"`, which is how every JWT starts (a JSON object opens with `{`). To read the contents, paste into this decoder, or decode each dot-separated part with a Base64 tool. Don't be impressed by the opaque look — JWTs aren't meant to be human-readable in their wire form, only programmatically parseable.