Blog
Wild & Free Tools

How to Decode a JWT in JavaScript and React (No Library)

Last updated: February 2026 5 min read
Quick Answer

Table of Contents

  1. The decodeJwt() Function
  2. Using in React
  3. Check Token Expiry
  4. npm Library vs No Library
  5. Frequently Asked Questions

You can decode a JWT in JavaScript in three lines using only built-in browser APIs — no jsonwebtoken, no jwt-decode package, no npm install. Here is the function and how to use it in React.

Decode JWT in JavaScript — Pure Browser APIs

function decodeJwt(token) {
  const parts = token.split('.');
  if (parts.length !== 3) throw new Error('Invalid JWT format');
  const payload = parts[1];
  // atob decodes base64; replace handles base64url chars
  const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));
  return JSON.parse(decoded);
}

// Usage
const payload = decodeJwt(token);
console.log(payload.sub);    // user ID
console.log(payload.email);  // email if present
console.log(payload.exp);    // expiry timestamp

This uses atob(), available in all modern browsers and Node.js 16+. The replace calls convert base64url encoding to standard base64 before decoding.

Note: some tokens have payload segments whose length causes atob to fail without padding. A safer version:

function decodeJwt(token) {
  const payload = token.split('.')[1];
  const padded = payload + '=='.slice(0, (4 - payload.length % 4) % 4);
  return JSON.parse(atob(padded.replace(/-/g, '+').replace(/_/g, '/')));
}

Using decodeJwt in React Components

A common pattern is to read user info from an access token stored in memory or a cookie:

import { useState, useEffect } from 'react';

function useCurrentUser(token) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    if (!token) return;
    try {
      const payload = decodeJwt(token);
      setUser({
        id: payload.sub,
        email: payload.email,
        name: payload.name,
        expiresAt: payload.exp * 1000  // convert to ms
      });
    } catch (e) {
      setUser(null);
    }
  }, [token]);

  return user;
}

// In your component
const user = useCurrentUser(accessToken);
if (user) return <p>Hello {user.name}</p>;

The exp * 1000 conversion is important — JWT timestamps are seconds since epoch, but JavaScript's Date uses milliseconds.

Sell Custom Apparel — We Handle Printing & Free Shipping

Check If a JWT Is Expired in JavaScript

function isJwtExpired(token) {
  try {
    const { exp } = decodeJwt(token);
    if (!exp) return false;  // no expiry = does not expire
    return Date.now() / 1000 > exp;
  } catch {
    return true;  // malformed token treated as expired
  }
}

// Before making an API call
if (isJwtExpired(accessToken)) {
  await refreshToken();
}

This is a client-side convenience check only. Your server must always validate the token independently — a malicious user can forge a client-side expiry check by replacing the token in memory.

Should You Use jwt-decode npm Package?

The jwt-decode npm package does the same thing as the function above — it is around 1KB and handles edge cases. There is no strong reason to install it for most projects since the vanilla implementation is short and easy to understand.

Use the npm package if:

Use the vanilla function if:

Either way, remember: client-side decoding is for reading claims only. Signature verification always belongs on the server.

Test Your Decoder Logic — Try the Browser Tool

Paste your JWT above to verify what the payload contains before writing your decoding logic.

Open Free JWT Decoder

Frequently Asked Questions

Does atob work in Node.js?

atob is available globally in Node.js 16 and later. In older Node.js versions, use Buffer.from(payload, "base64").toString("utf-8") instead of atob(payload).

Can I use this to validate the JWT signature?

No. This only decodes the payload — it does not verify the signature. Anyone can modify a JWT payload if the signature is not verified. Never trust decoded claims for security decisions without server-side validation.

What does "Invalid JWT format" mean?

The token must have exactly two dots separating three base64url segments. If you see this error, check that you have the full token and have not accidentally truncated it or included extra whitespace.

How do I decode a JWT in Angular?

The same decodeJwt() function works in Angular. You can create it as an injectable service or a standalone utility function. Angular does not provide a built-in JWT decoder.

Andrew Walsh
Andrew Walsh Developer Tools & API Writer

Andrew worked as a developer advocate at two SaaS startups writing API documentation used by thousands of engineers.

More articles by Andrew →
Launch Your Own Clothing Brand — No Inventory, No Risk