Aarunya AppsAarunya Apps
🔒 Security8 min read·August 19, 2026

How to Debug JWTs Without Pasting Them Into jwt.io

jwt.io is the first place most developers go to decode a JWT. It's convenient — but every token you paste there contains your authentication state. Here's the problem and the safer alternatives.

What a JWT actually contains

A JWT has three base64url-encoded parts separated by dots: header.payload.signature. The payload typically contains your user ID, roles, expiry time, and any claims your application adds. Pasting a live JWT into a third-party service means that service can see all of this.

// Decode in your browser console (no tools needed)
const [header, payload] = "eyJhbGci...".split(".")
console.log(JSON.parse(atob(header)))   // { alg: "HS256", typ: "JWT" }
console.log(JSON.parse(atob(payload)))  // { sub: "user_123", exp: 1711928400 }

The real risk with jwt.io

jwt.io decodes tokens client-side in your browser — the token is not sent to their server. For the decoding use case, this is relatively safe. The risk is habit: developers who routinely paste tokens into external tools eventually paste a production token with a long expiry, or paste one in a screen recording, or leave it in a chat log.

The lower-risk habit: decode in your browser console or use a local tool.

Decode without any tool (curl + jq)

TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

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

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

Common JWT errors and what they mean

  • TokenExpiredError — the exp claim is in the past. Refresh the token.
  • JsonWebTokenError: invalid signature — the token was signed with a different secret, or the payload was tampered with.
  • JsonWebTokenError: jwt malformed — the token string is missing a segment or has invalid base64 characters.
  • NotBeforeError — the nbf (not before) claim is in the future. The token is valid but can't be used yet.
  • Algorithm mismatch — the token header says RS256 but your verifier is configured for HS256. Always verify alg explicitly.

Verify a JWT in Node.js

import jwt from "jsonwebtoken"

try {
  const payload = jwt.verify(token, process.env.JWT_SECRET!, {
    algorithms: ["HS256"],  // Always specify — don't allow "none"
  })
  console.log(payload)
} catch (err) {
  if (err instanceof jwt.TokenExpiredError) // handle expiry
  if (err instanceof jwt.JsonWebTokenError) // handle invalid
}

Need to decode or verify a JWT without pasting it into an external service? Aarunya JWT Debugger runs entirely in your browser — the token never leaves your tab. Supports HS256, RS256, ES256, and 9 more algorithms.

Try the related tool

JWT Debugger — free, runs 100% in your browser.

Open JWT Debugger

Enjoyed this? Get notified when Pro launches.