Every web developer has done it. You’re debugging a tricky authentication issue, pull a JWT (JSON Web Token) out of your browser's local storage, and paste it straight into jwt.io or some random "Free Online JSON Formatter" website.
We all know we shouldn't. That token often contains sensitive user roles, PII (Personally Identifiable Information), or administrative access privileges. Yet, we do it anyway because it's faster than writing a decoding script in the terminal.
Pasting sensitive production data into random web tools is a massive security risk. You have no idea if that site is logging your tokens, saving your JSON payloads, or scraping your credentials.
And recently, this exact habit blew up.
In late 2025, security researchers at watchTowr investigated popular code-formatting sites like JSONformatter.org and CodeBeautify.org. What they found was terrifying: they were able to scrape over 80,000 saved developer snippets that were left publicly searchable on these sites.
The leaked data included:
- Administrative JWTs and API keys
- Database and FTP credentials
- CI/CD pipeline secrets
- Production customer PII (addresses, phone numbers, emails)
When you paste a JWT into a third-party website, you are handing a bearer token to a server you do not control. Even if the site claims to be "client-side only," there is no guarantee the data isn't being indexed for a public "Share this snippet" feature.
Secure Alternatives: Decoding JWTs Locally
If pasting into random websites is off the table, what are your offline options?
1. Bash & jq
Parse the full JWT directly in your terminal. You can add this helper function to your ~/.zshrc or ~/.bashrc:
# Add to ~/.zshrc:
decodejwt() {
echo "$1" | jq -R -s 'gsub("\n"; "") | split(".") | {header: (.[0] | @base64d | fromjson), payload: (.[1] | @base64d | fromjson), signature: .[2]}'
}
# Usage:
decodejwt "YOUR_JWT_STRING"
2. Node.js
A tiny local script (decode.js) that outputs the structured token using Node's built-in buffers:
const token = process.argv[2];
const [header, payload, signature] = token.split('.');
console.log(JSON.stringify({
header: JSON.parse(Buffer.from(header, 'base64url').toString()),
payload: JSON.parse(Buffer.from(payload, 'base64url').toString()),
signature
}, null, 2));
3. Python
A quick Python script that automatically handles Base64Url padding:
import sys, base64, json
def dec(s):
return json.loads(base64.b64decode(s + '=' * (-len(s) % 4)))
h, p, s = sys.argv[1].split('.')
print(json.dumps({'header': dec(h), 'payload': dec(p), 'signature': s}, indent=2))
4. Browser DevTools Console (Offline)
Zero-install method. Open Chrome/Safari DevTools Console (F12) and run:
const decodeJWT = (t) => t.split('.').slice(0, 2).map(p => JSON.parse(atob(p.replace(/-/g, '+').replace(/_/g, '/'))));
console.log(decodeJWT("YOUR_JWT_STRING"));
The Best of Both Worlds: An Offline Native Tool
All of these CLI solutions are 100% secure. But context-switching to a terminal and writing commands every single time you need to check a token expiration date creates friction.
We need tools that are as fast as a web app, but 100% offline and secure.
That’s why I built L2Cache — a native macOS developer tool and smart clipboard layer.
Instead of sending your clipboard data to the web, L2Cache handles developer data directly on your Mac:
- Instant JWT Decoding: Automatically detects when a JWT is copied and shows the decoded header, payload claims, and expiration in a clean popup with 1 click.
- Local JSON Formatting: Beautify and syntax-highlight dirty JSON responses without third-party web tools.
- 100% On-Device: Built in native Swift + SQLite with zero telemetry.
Protect your tokens. Keep your credentials on your machine.
L2Cache is currently free on the Mac App Store for early access.

Top comments (0)