Back to blog
TutorialsSeptember 29, 2025

How to Decode a JWT Token Safely (Without Leaking Your Secret)

JWTs are everywhere in modern auth. Decoding them is easy — doing it without leaking sensitive data takes care.

JWTauthenticationdeveloper toolssecurity

JSON Web Tokens (JWTs) carry user identity and permission claims in nearly every modern web application. When debugging an auth flow, you need to decode them constantly to check claim values, verify expiration, and confirm the issuer.

The mistake most developers make: they paste production JWTs into the first online JWT decoder they find on Google. Some of those decoders log requests. Some of them ask for your secret to "verify the signature" which means they now have your signing key. Both are security incidents waiting to happen.

Here's how to decode JWTs safely.

What's in a JWT

A JWT has three parts separated by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Reading left to right:

  1. Header (Base64-URL encoded JSON) the algorithm used and the token type
  2. Payload (Base64-URL encoded JSON) the claims (user ID, expiration, custom data)
  3. Signature (Base64-URL encoded bytes) the cryptographic signature, only verifiable with the secret/public key

The header and payload are not encrypted they are just encoded. Anyone with the token can read them.

Method 1: Browser-Based JWT Decoder (Safest)

The fastest and safest method: paste the token into a browser-based JWT decoder.

A proper client-side decoder does three things:

  1. Splits the token on the . character
  2. Base64-URL decodes the header and payload locally in your browser
  3. Pretty-prints both as JSON

Your token is decoded entirely in JavaScript on your machine. Nothing is uploaded.

Example. The token above decodes to:

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}

The signature shows opaque there is no way to verify it without the signing key.

Method 2: Command Line

If you're already in a terminal:

TOKEN="eyJhbGc..."

# Decode header
echo "$TOKEN" | cut -d. -f1 | base64 -d 2>/dev/null

# Decode payload
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null

The 2>/dev/null suppresses padding warnings Base64-URL strings often need padding added before standard base64 -d accepts them.

A cleaner one-liner using jq:

echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq

When to use: scripting, automated checks, terminal-only environments.

Method 3: Browser DevTools Console

If the JWT is already in your browser (cookie, localStorage, or a network request):

const token = "eyJhbGc...";
const [header, payload] = token.split('.').slice(0, 2)
  .map(part => JSON.parse(atob(part.replace(/-/g, '+').replace(/_/g, '/'))));

console.log(header);
console.log(payload);

When to use: debugging in DevTools, automated tests in the browser console.

What NOT to Do

The dangerous patterns to avoid:

Don't paste JWTs into random online tools without checking

Many online JWT decoders are server-side they upload your token to process it. If the server logs requests (most do, for debugging), your token is sitting in someone's log file.

A production JWT can be replayed by anyone who has it before it expires. If yours is logged on a third-party server, it's effectively compromised.

Don't paste your signing key anywhere ever

Some online JWT tools offer "signature verification" paste your token and your secret, and they'll verify it. The moment you paste your secret, you've handed over the key that signs every token your app issues.

If a tool asks for your secret or public key, close it. Verify signatures locally using your own auth library.

Don't share JWTs in screenshots or chat

Even if you redact part of the token, the structure (header type and algorithm) and any unredacted segments give attackers information. Treat JWTs like passwords.

Don't decode production tokens in untrusted environments

A production JWT for an admin user is the same as the admin's password (until expiration). Don't decode it on a coworker's laptop, in a coffee shop kiosk, or anywhere you wouldn't paste a password.

Verifying Signature vs Decoding

Decoding tells you what's in the token. Signature verification tells you whether the token is genuine. They're different operations.

  • Decoding requires no secret anyone can do it
  • Signature verification requires the signing secret (HS256) or public key (RS256, ES256)

Verification belongs in your auth library (jsonwebtoken for Node.js, pyjwt for Python, jjwt for Java). It's a 3-line operation in any language. Never paste your secret into a web tool to do it.

Common Claims Worth Checking

When debugging, these are the claims you'll inspect most:

  • sub subject (typically the user ID)
  • iat issued at (Unix timestamp)
  • exp expiration (Unix timestamp)
  • iss issuer (who created the token)
  • aud audience (who the token is for)
  • nbf not before (token isn't valid before this time)

The JWT decoder automatically calculates expiry status from exp and shows whether the token is still valid.

Quick Reference

SituationUse this
One-off decodeBrowser JWT decoder
Token already in DevToolsDevTools console one-liner
Scripting or CIcut + base64 + jq pipeline
Verifying signatureYour server-side auth library

For everyday JWT decoding, use a browser-based decoder that processes everything client-side. For verification, use your own code never a web tool.

Related articles