UUsefulCrate Your files never leave your browser

HomeGuides › Developer

Why you should never paste a JWT into an online decoder

A JWT is not a description of a login. It is the login. Pasting one into a stranger's website is roughly equivalent to giving them your session.

2026-09-24 · 7 min read

Short answer: don't paste it anywhere. A JWT is a working credential rather than a description of one, so whatever server receives it can usually act as you until it expires — and you have no way to know whether it was logged, stored or replayed. Decode it locally instead; the payload is only Base64 and your browser can read it without sending anything.

Search for "jwt decoder" and the first results are all websites that ask you to paste a token into a box. They work fine. That is the problem.

A JSON Web Token is not a description of a login. It is the login. Whatever server issued it will accept the token itself as proof of identity, without any further check, until it expires. Pasting one into a third-party website is therefore closer to handing over your session than to looking something up.

What the site actually receives

The box in the middle of the page is not a local function. It is a form, and pressing decode sends the token to a server — usually over HTTPS, usually to a site run by someone you have never heard of, with no way to know what happens to it afterwards.

The server can see the entire token, which means it can see:

An operator who wanted to be malicious would not need to do anything clever. They would log the request body. Tokens arriving at free decoding services are, by definition, tokens that were just used in a live session, and the traffic to those sites is free and continuous.

"Nothing is logged" is not a testable claim

Some of these sites say they do not log requests. That may well be true, and the operator may well be honest. But there is no way for you to verify it from outside, and the cost of being wrong is not symmetric: being right saves you the thirty seconds it would take to decode the token locally, and being wrong means someone holds a working credential for your application.

There is also the smaller, likelier failure: a hosted service that keeps a cache of recently decoded tokens for performance, or a third-party analytics script on the page that picks up form fields, or a breach of the service six months from now that dumps historical request logs. None of these require ill intent.

Decoding a JWT is trivial, which is the point

A JWT has three parts separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 . eyJzdWIiOiIxMjMiLCJuYW1lIjo... . dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

The first two are Base64URL-encoded JSON. Decoding them is a string operation that takes milliseconds, and it involves no cryptography whatsoever:

header  = JSON.parse(base64url_decode(parts[0]))
payload = JSON.parse(base64url_decode(parts[1]))
signature = parts[2]        // opaque bytes, not decoded

That is the entire algorithm. There is nothing here that needs a server — which makes it hard to justify sending a live credential across the internet to have it done.

You can confirm this yourself in a browser console, though it is fiddly because of the URL-safe alphabet and the missing padding. The local JWT decoder here does the same job with the timestamps converted to readable dates, and the page is a static file with no network calls at all — you can verify that in the Network panel of your developer tools.

Decoding is not verifying, and the sites blur this

Almost every online decoder will show you a decoded payload and let you believe the token is valid. It has not checked anything. Decoding proves only that the token is well-formed JSON inside Base64.

Verifying a signature requires the signing key, or the public key if the token uses an asymmetric algorithm such as RS256. That is a server-side operation by nature — the whole point of a signature is that a party without the key cannot produce one. A web page cannot verify a token for you, no matter what its interface implies.

So the honest description of every decoder, hosted or local, is the same: this shows you what the token claims, not whether it is trustworthy. Treat the payload as an assertion, not as proof.

The mistake underneath the mistake

If you are reaching for a decoder because you need to see what is in a token during development, the token you are holding is probably a real one from a real session. That is the actual problem worth fixing.

What to do instead

  1. Decode locally. Any browser-based decoder that makes no network requests will do; the one on this site is here.
  2. If you must use a hosted one, use a token you have already revoked, or a throwaway from a test environment.
  3. Never paste a token from production into anything you did not write.

This is the same reasoning that applies to hashing passwords or decoding Base64 in a browser: the input is the secret, and the value of running it locally is not a preference but the entire point. If a tool that handles credentials sends them somewhere, it has already failed at its job.

← All guides