{}JSONLint.app

JWT Decoder

Decode and inspect JSON Web Tokens. Paste your JWT below to view the header and payload:

What is a JWT?

JSON Web Token (JWT) is a compact, URL-safe way to represent claims between two parties. JWTs are commonly used for authentication and authorization in web applications and APIs.

JWT Structure

A JWT consists of three parts separated by dots:

header.payload.signature
PartContentsPurpose
HeaderAlgorithm, token typeDescribes how the token is signed
PayloadClaims (user data)Contains the actual data/claims
SignatureEncrypted hashVerifies the token is authentic

Common JWT Claims

The payload typically contains these standard claims:

ClaimNameDescription
subSubjectWho the token is about (usually user ID)
iatIssued AtWhen the token was created (Unix timestamp)
expExpirationWhen the token expires (Unix timestamp)
issIssuerWho issued the token
audAudienceIntended recipient of the token

Security Considerations

Important: This tool decodes JWTs but does not verify signatures. Anyone can decode a JWT and read its contents — the signature only prevents tampering.

  • Never trust a JWT without verifying its signature on your server
  • Don't store sensitive data in JWT payloads (they're not encrypted)
  • Always check the exp claim to reject expired tokens
  • Validate the iss and aud claims match expected values

JWT vs Session Cookies

FeatureJWTSession Cookie
StorageClient-sideServer-side
ScalabilityStateless, easy to scaleRequires session store
RevocationHarder (needs blocklist)Easy (delete session)
SizeLarger (contains data)Small (just an ID)

Working with JWTs in Code

JavaScript

// Decode without verifying (like this tool)
function decodeJWT(token) {
  const payload = token.split('.')[1];
  return JSON.parse(atob(payload));
}

// With a library (recommended for verification)
import jwt from 'jsonwebtoken';
const decoded = jwt.verify(token, secretKey);

Python

import jwt

# Decode without verifying
decoded = jwt.decode(token, options={"verify_signature": False})

# Decode with verification
decoded = jwt.decode(token, secret_key, algorithms=["HS256"])

Related Tools

Frequently Asked Questions

Is it safe to decode a JWT in the browser?

Yes, decoding is safe. JWTs are not encrypted — they're just Base64-encoded. The signature protects against tampering, not reading. Never put sensitive information in a JWT that you wouldn't want users to see.

Why does my JWT show as expired?

The exp claim is a Unix timestamp. If the current time is past this value, the token is expired. Tokens typically expire in minutes to hours for security.

Can I verify the signature with this tool?

No. Signature verification requires the secret key or public key used to sign the token, which should never be shared publicly. Use server-side code to verify signatures.

Common Mistakes & Pro Tips

  • Decoding is not verifying — the signature is uncheckedThis tool Base64URL-decodes the header and payload so you can read them, but it does not verify the signature against a secret or public key. A decoded token can still be expired, tampered with, or forged; never trust its contents for authorization without verifying the signature server-side.
  • A JWT is signed, not encrypted — the payload is publicAnyone holding the token can decode the payload and read every claim; signing only proves integrity, not confidentiality. Never put passwords, secret keys, or sensitive personal data in a JWT payload, because it is effectively plaintext to whoever receives it.
  • exp and iat are Unix seconds, not millisecondsPer RFC 7519, exp, iat, and nbf are NumericDate values — seconds since 1970-01-01 UTC. JavaScript's Date.now() returns milliseconds, so multiply these claims by 1000 before constructing a Date, or you'll compute a timestamp in 1970.
  • JWTs use Base64URL, not standard Base64The three segments are encoded with the URL-safe alphabet (- and _ instead of + and /) and typically have their = padding stripped. A standard Base64 decoder may fail on a JWT segment, which is why a dedicated decoder handles the padding and alphabet correctly.
  • alg: none is a red flagA header specifying "alg": "none" means the token is unsigned, a historically exploited way to bypass verification. If you see it on a token that's supposed to be authenticated, treat the token as untrusted and reject it on the server.

Frequently Asked Questions

Does decoding a JWT verify that it's valid?

No. Decoding only Base64URL-decodes the header and payload so you can read them; it performs no signature verification whatsoever. To confirm a token is authentic and untampered, the receiving server must verify the signature using the issuer's secret (for HMAC) or public key (for RSA/ECDSA), and also check claims like exp. Treat any decoded payload as unverified until that happens.

Can anyone read the contents of my JWT?

Yes. A standard JWT is signed but not encrypted, so its payload is just Base64URL-encoded text that anyone with the token can decode and read. The signature prevents undetected modification, not reading. For this reason you must never place secrets, passwords, or sensitive personal information in a JWT payload.

How do I check when a token expires?

Look at the exp claim in the decoded payload. It's a Unix timestamp in seconds (UTC), so convert it by multiplying by 1000 to get JavaScript milliseconds, or compare it directly to the current time in seconds. If exp is earlier than now, the token is expired — though only signature verification confirms the token was legitimate in the first place.

What do the iss, iat, and sub claims mean?

These are registered claims from RFC 7519: iss is the issuer (who created the token), iat is issued-at (a Unix-seconds timestamp), and sub is the subject (usually the user or entity the token is about). Other common ones include aud (intended audience), nbf (not valid before), and jti (a unique token ID). They're conventions, so an issuer may include only some of them.

Why are there three parts separated by dots?

A JWT is header.payload.signature, with each part Base64URL-encoded and joined by periods. The header names the signing algorithm and token type, the payload holds the claims, and the signature is computed over the first two parts to detect tampering. This decoder shows you the header and payload; the signature can only be checked with the right key.

Is it safe to paste a real token into this decoder?

Yes, from a transmission standpoint — decoding happens entirely in your browser and the token is never uploaded. That said, remember a live token grants whatever access it represents, so avoid pasting it anywhere you don't control, and prefer expired or test tokens when sharing screenshots.

Can I decode an expired or invalid JWT?

Yes. Decoding is purely structural, so expiry, a bad signature, or a wrong audience don't stop you from reading the header and payload. This is useful for debugging — you can inspect why a token was rejected — but it also underlines that decoding tells you nothing about whether the token is trustworthy.