JWT Decoder
Decode and inspect JWT tokens instantly. View header, payload, and signature. Check expiration, issuer, and claims. Free online JWT decoder — no data sent to any server.
Paste a JWT token and click Decode
What is a JWT (JSON Web Token)?
A JSON Web Token (JWT, pronounced "jot") is an open standard (RFC 7519) for securely transmitting information between parties as a compact, URL-safe JSON object. JWTs are the backbone of modern authentication and authorization — when you log into a web application, receive an OAuth2 access token, or authenticate with an API, you're almost certainly using JWTs. They're used by every major identity provider including Auth0, AWS Cognito, Firebase Auth, Okta, and Azure AD.
What makes JWTs powerful is their self-contained nature: the token itself carries all the information needed to verify the user's identity and permissions. Unlike session-based authentication where the server must look up session data in a database on every request, a JWT can be verified using only the signing key. This stateless property makes JWTs ideal for microservices architectures, serverless functions, and distributed systems where sharing session state between services would be impractical.
This decoder parses JWT tokens entirely in your browser — no data is ever sent to a server. It splits the token into its three components (header, payload, signature), Base64URL-decodes each part, and displays the JSON contents with syntax highlighting. It also checks the exp claim against the current time to tell you whether the token is still valid. This is invaluable when debugging authentication issues, inspecting tokens from OAuth flows, or verifying that your token service is issuing correct claims.
JWTs work alongside many other developer tools. The exp, iat, and nbf claims are Unix timestamps — use our converter to check exact expiration times. The sub claim often contains a UUID identifying the user. JWT payloads are JSON objects that you can format with our JSON Formatter. And the token itself is Base64URL-encoded, which is a URL-safe variant of standard Base64.
JWT Structure
A JWT consists of three parts separated by dots (.):
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
|_________________________|.___________________________|.___________________________________|
Header Payload Signature- Header: Contains metadata — the token type (
"typ": "JWT") and the signing algorithm ("alg": "HS256","RS256", etc.). - Payload: Contains the claims — statements about the user (like user ID, email, roles) and metadata (like expiration time). This is the main data carrier.
- Signature: Created by signing the encoded header and payload with a secret key (HMAC) or private key (RSA/ECDSA). Used to verify the token hasn't been tampered with.
Common JWT Claims
sub(Subject) — Identifies the principal (usually a user ID or UUID)iat(Issued At) — Unix timestamp when the token was createdexp(Expiration) — Unix timestamp after which the token is invalidnbf(Not Before) — Unix timestamp before which the token is not validiss(Issuer) — Who issued the token (e.g., your auth server's URL)aud(Audience) — Who the token is intended for (e.g., your API's identifier)jti(JWT ID) — Unique identifier for the token (for revocation tracking)scope— OAuth2 scopes granted to the tokenroles— Application-specific roles or permissions
Practical Examples
1. Decode a JWT in JavaScript (without a library):
function decodeJWT(token) {
const [header, payload, signature] = token.split('.');
return {
header: JSON.parse(atob(header)),
payload: JSON.parse(atob(payload)),
signature: signature
};
}
const decoded = decodeJWT(myToken);
console.log(decoded.payload.sub); // User ID
console.log(decoded.payload.exp); // Expiration timestamp2. Check if a JWT is expired:
function isTokenExpired(token) {
const payload = JSON.parse(atob(token.split('.')[1]));
if (!payload.exp) return false; // No expiration set
return payload.exp < Math.floor(Date.now() / 1000);
}
if (isTokenExpired(accessToken)) {
// Refresh the token or redirect to login
}3. Create a JWT in Node.js (using jsonwebtoken):
const jwt = require('jsonwebtoken');
const token = jwt.sign(
{ sub: 'user-123', role: 'admin' },
process.env.JWT_SECRET,
{ expiresIn: '1h', issuer: 'my-app' }
);
// eyJhbGciOiJIUzI1NiIs...4. Verify a JWT in Python:
import jwt
try:
payload = jwt.decode(
token,
public_key,
algorithms=['RS256'],
audience='my-api'
)
user_id = payload['sub']
except jwt.ExpiredSignatureError:
print("Token has expired")
except jwt.InvalidTokenError:
print("Invalid token")5. Extract JWT from an Authorization header:
// Express.js middleware
function extractToken(req, res, next) {
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
req.token = authHeader.slice(7); // Remove "Bearer " prefix
}
next();
}Signing Algorithms
- HS256 (HMAC-SHA256): Symmetric — same secret key signs and verifies. Simple but requires sharing the secret with all verifiers.
- RS256 (RSA-SHA256): Asymmetric — private key signs, public key verifies. Ideal when multiple services need to verify tokens without having the signing key.
- ES256 (ECDSA-SHA256): Asymmetric with smaller keys than RSA. Faster verification and shorter signatures. Increasingly popular for new systems.
- EdDSA (Ed25519): Modern asymmetric algorithm. Fastest verification, smallest signatures, and strong security properties.
Security Best Practices
- Always validate the signature — never trust a JWT payload without verification.
- Check the
expclaim — reject expired tokens. - Validate
issandaudclaims — ensure the token was issued by your auth server for your application. - Never store sensitive data in the payload — JWTs are encoded, not encrypted. Anyone with the token can read the payload.
- Use short expiration times (15 minutes for access tokens) with refresh token rotation.
- Never use the
"alg": "none"algorithm in production — it disables signature verification.
Frequently Asked Questions
Is it safe to decode a JWT in the browser?
Yes, decoding (reading the contents) is perfectly safe and is done entirely client-side. JWT payloads are only Base64URL-encoded, not encrypted — anyone who has the token can read its contents. The security of a JWT comes from its signature, which proves the token hasn't been tampered with. This tool decodes tokens in your browser without sending any data to a server. However, you should never paste tokens from production systems into untrusted online tools.
What is the difference between JWT encoding and encryption?
Standard JWTs (JWS — JSON Web Signature) are signed but not encrypted. The payload is Base64URL-encoded, which is a reversible encoding — not encryption. Anyone with the token can decode and read the payload. If you need encrypted tokens, use JWE (JSON Web Encryption), which encrypts the payload so only the intended recipient can read it. In practice, most systems use signed JWTs and simply avoid putting sensitive data in the payload.
How do I handle JWT expiration in a single-page application?
The standard approach is to use short-lived access tokens (15-60 minutes) paired with longer-lived refresh tokens. When the access token expires, silently request a new one using the refresh token. Implement this by: 1) Checking the exp claim before each API call, 2) If expired or about to expire, call your refresh endpoint, 3) Retry the original request with the new token. Libraries like axios-auth-refresh automate this pattern. Store refresh tokens in httpOnly cookies for security.
What does "invalid signature" mean when decoding a JWT?
An "invalid signature" error means the token's signature doesn't match what the verification key produces. Common causes: 1) Using the wrong secret or public key to verify, 2) The token was tampered with (payload modified after signing), 3) Using the wrong algorithm (e.g., trying to verify an RS256 token with an HS256 secret), 4) The token was issued by a different auth server than expected. Always ensure your verification key matches the issuer's signing key.
Should I store JWTs in localStorage or cookies?
Neither option is perfect — each has tradeoffs. localStorage is vulnerable to XSS attacks (malicious scripts can read the token), while cookies are vulnerable to CSRF attacks. The recommended approach is: store access tokens in memory (JavaScript variable) for the shortest exposure, and store refresh tokens in httpOnly, Secure, SameSite=Strict cookies where JavaScript cannot access them. This protects against both XSS and CSRF while maintaining a good user experience.
Related Tools
- Unix Timestamp Converter — Convert JWT exp/iat claims to readable dates
- Base64 Encoder/Decoder — Decode the Base64URL-encoded JWT segments
- JSON Formatter — Format the decoded JWT payload for readability
- UUID Generator — Generate UUIDs commonly used as JWT subject claims