← Back to Blog

Build a JWT Debugger in the Browser (No Libraries Needed)

May 13, 2026 3 min read By CodeTidy Team

The Frustrating World of JWT Debugging

As developers, we've all been there - staring at a cryptic error message, trying to decipher the contents of a JSON Web Token (JWT). It's a frustrating experience, especially when all we need is a simple way to decode and inspect the token's contents. But fear not, dear reader, for we're about to build a JWT debugger in the browser, no libraries needed!

Table of Contents

  • Understanding JWTs and the Need for a Debugger
  • Decoding JWTs with atob() and JSON.parse()
  • Extracting Claims and Checking Expiration
  • Signature Verification: The Final Piece of the Puzzle
  • Putting it all Together: The JWT Debugger
  • Key Takeaways
  • FAQ

Understanding JWTs and the Need for a Debugger

A JSON Web Token (JWT) is a compact, URL-safe way to represent claims between two parties. It consists of three parts: a header, a payload, and a signature. The header and payload are Base64-encoded and separated by dots (.). But what happens when things go wrong and we need to inspect the token's contents?

We often find ourselves copying the token into a terminal or a separate tool, only to realize that we need to decode the Base64, parse the JSON, and then extract the relevant information. It's a tedious process, and that's where our JWT debugger comes in.

Decoding JWTs with atob() and JSON.parse()

To start building our debugger, we need to decode the Base64-encoded header and payload. We can use the atob() function to achieve this. Here's an example:

const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaGFuIjoiMjMwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c";
const decodedHeader = atob(token.split('.')[0]);
const decodedPayload = atob(token.split('.')[1]);

console.log(decodedHeader); // Output: {"alg":"HS256","typ":"JWT"}
console.log(decodedPayload); // Output: {"sub":"1234567890","name":"Johan","iat":1631234567}

Notice how we split the token into its three parts using the dot (.) as a separator. We then decode each part using atob().

Next, we can use JSON.parse() to parse the decoded header and payload into JavaScript objects:

const header = JSON.parse(decodedHeader);
const payload = JSON.parse(decodedPayload);

console.log(header); // Output: { alg: "HS256", typ: "JWT" }
console.log(payload); // Output: { sub: "1234567890", name: "Johan", iat: 1631234567 }

Extracting Claims and Checking Expiration

Now that we have our decoded and parsed header and payload, we can extract the relevant claims and check the expiration time. Let's create a function to do just that:

function extractClaims(payload) {
  const claims = {
    sub: payload.sub,
    name: payload.name,
    iat: payload.iat,
    exp: payload.exp,
  };

  return claims;
}

const claims = extractClaims(payload);
console.log(claims); // Output: { sub: "1234567890", name: "Johan", iat: 1631234567, exp: 1631234567 }

We can also check the expiration time by comparing it to the current timestamp:

function isExpired(claims) {
  const currentTime = Math.floor(Date.now() / 1000);
  return claims.exp < currentTime;
}

console.log(isExpired(claims)); // Output: false

Signature Verification: The Final Piece of the Puzzle

The final piece of our JWT debugger is signature verification. We can use the crypto library to verify the signature. Here's an example:

const crypto = require('crypto');

function verifySignature(token, secret) {
  const signature = token.split('.')[2];
  const expectedSignature = crypto.createHmac('sha256', secret).update(token.split('.')[0] + '.' + token.split('.')[1]).digest('base64');
  return signature === expectedSignature;
}

const secret = "your_secret_key_here";
console.log(verifySignature(token, secret)); // Output: true

Putting it all Together: The JWT Debugger

Now that we have all the pieces, let's put them together into a single function:

function jwtDebugger(token, secret) {
  const decodedHeader = atob(token.split('.')[0]);
  const decodedPayload = atob(token.split('.')[1]);
  const header = JSON.parse(decodedHeader);
  const payload = JSON.parse(decodedPayload);
  const claims = extractClaims(payload);
  const isExpired = isExpired(claims);
  const isValid = verifySignature(token, secret);

  return {
    header,
    payload,
    claims,
    isExpired,
    isValid,
  };
}

const token = "your_token_here";
const secret = "your_secret_key_here";
const result = jwtDebugger(token, secret);
console.log(result);

Key Takeaways

  • We can use atob() and JSON.parse() to decode and parse JWTs in the browser.
  • We can extract claims and check expiration times using simple JavaScript functions.
  • We can verify signatures using the crypto library.
  • By putting it all together, we can create a powerful JWT debugger in the browser.

FAQ

Q: What is a JWT?

A: A JSON Web Token (JWT) is a compact, URL-safe way to represent claims between two parties.

Q: Why do I need a JWT debugger?

A: A JWT debugger helps you inspect and verify the contents of a JWT, making it easier to debug and troubleshoot issues.

Q: Can I use this JWT debugger in production?

A: While this debugger is suitable for development and testing, you should consider using a more robust and secure solution in production.

AI agent tools available. The CodeTidy MCP Server gives Claude, Cursor, and other AI agents access to 60+ developer tools. One command: npx @codetidy/mcp