Why you'd want to decode a JWT
A JSON Web Token (JWT) is the little three-part string your auth system hands out after a login. It looks like gibberish: eyJhbGci... dot eyJzdWIi... dot SflKxw.... But the first two parts are just base64url-encoded JSON, so any of those segments can be read back into plain text. Decoding a JWT lets you see exactly which user it represents, which roles or scopes it grants, when it was issued, and — the question that bites everyone — whether it has already expired.
You'd reach for this when an API keeps returning 401, when you're wiring up a new OAuth or OIDC flow and need to confirm the aud and iss claims match, or when QA hands you a token and asks why a permission isn't working. The key thing to understand up front: decoding is not the same as verifying. Anyone can read a JWT's contents; only the server holding the secret can prove the signature is genuine. The steps below cover the reading part, which is safe to do locally.
How to decode a JWT
-
Open the JWT Decoder. It runs entirely in your browser — the token you paste is decoded with your machine's own JavaScript, never uploaded to a server, and there's no sign-up.
-
Paste your token into the "Paste JWT Token" box. The tool decodes as you type, so you don't need to press a button. If you don't have a token handy and just want to see how it behaves, click Sample to load a working example.
-
Watch the validation banner. A green bar confirms a valid structure — three base64url segments separated by dots. A red bar tells you what's wrong, for example "JWT must have 3 parts separated by dots" or "Payload is not valid base64url-encoded JSON." This is the fastest way to catch a truncated or mangled token.
-
Read the Header. This panel shows the algorithm (
alg) and type (typ). The decoder also rates the algorithm —HS256,RS256, andES256are flagged as recommended, whilealg: noneis flagged as insecure and "not safe for production." -
Read the Payload. This is the part you usually care about:
sub(the user ID),email,roleorroles,scope, and your own custom claims. The syntax-highlighted JSON makes nested objects easy to scan, and you can copy any panel with the copy icon. -
Check the expiry status. A status card shows Valid, Expired, Not Yet Valid, or No Expiry Set, with a live countdown of the time remaining. If your "logged-in" requests are failing, this is almost always where you'll find the answer.
-
Open the Claim Explanations glossary. Standard claims like
iss,aud,nbf, andjtiget a plain-English description, and timestamp claims (exp,iat,nbf) are converted from Unix seconds into your local date and time, so you don't have to do the math by hand. -
If you need the raw signature, click Reveal in the Signature panel. It stays hidden by default so you don't accidentally screenshot a sensitive token. Remember: the decoder shows the signature but does not verify it — that requires your secret key on the server.
That's the whole reading workflow. Two extra tabs are worth knowing about: Builder lets you compose a test JWT structure (it outputs an unsigned token with a placeholder signature, meant for shaping a payload, not for production), and Snippets gives ready-made verify-and-sign code for Node, Python, Go, Java, PHP, and Ruby.
Tips and common problems
-
"Invalid JWT structure" but the token looks fine. You probably copied a trailing space, a quote, or only two of the three segments. The token must contain exactly two dots. Trim whitespace and re-paste.
-
The payload decodes but a value looks scrambled. JWTs are base64url-encoded, which is a variant of standard base64 (
-and_instead of+and/). If you're decoding a single segment by hand in another tool, use a base64 decoder that supports the URL-safe alphabet, or you'll get garbage. -
Decoding is not verifying. The contents are readable by anyone, so never trust a decoded claim for a security decision in client code. Signature verification belongs on the server, where the secret lives. To experiment with how a signature is produced from a header and payload, an HMAC generator shows the hashing step behind
HS256. -
Don't paste production tokens you don't control. Even though this tool decodes locally, a JWT is a live credential until it expires. Use the Sample token or a throwaway test token when you're just exploring.
-
Times look off by hours? JWT timestamps are in UTC Unix seconds. The decoder converts them to your local timezone in the Timeline section — compare against UTC, not your wall clock, when reading the raw numbers.
FAQ
Is my token uploaded anywhere when I decode it? No. The decoder processes everything in your browser using local JavaScript. Nothing is sent to a server, and there's no account to create. You can confirm this by decoding with your network connection off.
Can this tool tell me if a token is valid?
It validates the structure (three correct base64url segments) and tells you whether the token is expired or not yet active based on the exp and nbf claims. It cannot verify the signature, because that requires the secret or public key that only your server should hold. A decoded-but-unverified token can still be forged.
Why can I read the payload without any password? Because a JWT is encoded, not encrypted. The header and payload are plain base64url JSON. That's by design — the signature exists to detect tampering, not to hide the contents. The practical lesson: never put passwords, card numbers, or other secrets inside a JWT payload.
How do I create a signed token, not just read one? The decoder's Builder tab produces an unsigned structure for testing. To generate a properly signed token, use the dedicated JWT generator, and sign it with your real secret on the server side.
Building or debugging an auth flow? Pair the decoder with the JWT generator and base64 encoder, and see our essential guide to developer tools for the wider toolkit.