If you work with any modern authentication system — OAuth, Auth0, Firebase, or your own backend API — you have almost certainly encountered a JWT. They appear in HTTP headers, local storage, and API responses, but what exactly is inside one, and how do you read it safely?

What is a JWT?

JWT stands for JSON Web Token. It is a compact, URL-safe string used to securely transmit information between two parties. The information is encoded — not encrypted — so it can be read by anyone who has the token.

JWTs are most commonly used for authentication. After a user logs in, the server issues a JWT. The client stores it and sends it with every subsequent request. The server verifies the token's signature to confirm it is legitimate — without needing to query a database on every request.

The structure of a JWT

A JWT is three Base64URL-encoded strings joined by dots:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header.Payload.Signature

Part 1 — Header

The header describes the token type and the algorithm used to sign it:

{
  "alg": "HS256",   // signing algorithm
  "typ": "JWT"     // token type
}

Part 2 — Payload

The payload contains the actual data — called claims. These are statements about the user and any additional metadata:

{
  "sub": "1234567890",     // subject (usually user ID)
  "name": "John Doe",       // custom claim
  "email": "[email protected]",
  "role": "admin",
  "iat": 1516239022,       // issued at (Unix timestamp)
  "exp": 1516242622        // expiry (Unix timestamp)
}

Standard claims include:

Part 3 — Signature

The signature is created by the server using the header, the payload, and a secret key:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

The signature is what makes JWTs trustworthy. Anyone can read the header and payload, but only the server that holds the secret key can produce a valid signature. If someone tampers with the payload, the signature will no longer match and the token will be rejected.

Important: JWTs are encoded, not encrypted. Anyone who has the token can read the header and payload. Never store sensitive data like passwords or payment details in a JWT payload.

How to decode a JWT

Decoding a JWT means reading the header and payload — it requires no secret key. You are simply reversing the Base64URL encoding.

In JavaScript:

function decodeJWT(token) {
  const parts = token.split('.');
  const header = JSON.parse(atob(parts[0]));
  const payload = JSON.parse(atob(parts[1]));
  return { header, payload };
}

// Usage
const decoded = decodeJWT(myToken);
console.log(decoded.payload.email); // "[email protected]"

Note: atob() decodes standard Base64. JWT uses Base64URL which replaces + with - and / with _. For production use, handle this substitution or use a proper JWT library.

Verifying vs decoding

Decoding and verifying are two different things:

When you use a JWT decoder tool to inspect a token, you are decoding — not verifying. The token's claims may be readable but that does not mean the token is legitimate.

Is it safe to paste a JWT into a decoder tool?

It depends on what the token contains and which tool you use. Two things to check:

Our JWT Decoder runs entirely in your browser. The token you paste is never sent anywhere — it is decoded using JavaScript on your own device.

Decode a JWT token instantly

Paste any JWT and see the decoded header, payload, and expiry time. Runs entirely in your browser — nothing is ever sent to a server.

Open JWT Decoder →