JWT Decoder
This JWT decoder lets you inspect JSON Web Tokens in your browser. View header, payload, signature, expiration status, and claims instantly.
Paste a JSON Web Token (JWT) and instantly see its decoded header, payload, and signature. The tool checks expiration status, displays all claims in syntax-highlighted JSON, and shows timestamps in human-readable format. Everything runs in your browser - your tokens are never sent to a server.
About JWT Decoder
What Is a JWT?
A JSON Web Token is a compact, URL-safe string used to securely transmit claims between two parties. It is the most common token format for API authentication, single sign-on (SSO), and stateless session management. A JWT consists of three Base64URL-encoded parts separated by dots:
| Part | Contains | Example Content |
|---|---|---|
| Header | Algorithm and token type | {"alg": "HS256", "typ": "JWT"} |
| Payload | Claims (the actual data) | {"sub": "1234", "name": "Alice", "iat": 1712390400} |
| Signature | Verification hash | HMAC-SHA256(base64url(header) + "." + base64url(payload), secret) |
The header and payload are simply Base64URL-encoded JSON - not encrypted. Anyone who has the token can decode and read the payload. The signature prevents tampering but does not hide the contents.
Registered JWT Claims
RFC 7519 defines a set of standard claims. These are not required, but most JWTs use at least iss, sub, exp, and iat.
| Claim | Full Name | Type | Purpose |
|---|---|---|---|
| iss | Issuer | String | Who created and signed the token (e.g., "auth.example.com") |
| sub | Subject | String | Who the token represents (usually a user ID) |
| aud | Audience | String or array | Which service(s) should accept this token |
| exp | Expiration Time | Unix timestamp | Token is invalid after this time |
| nbf | Not Before | Unix timestamp | Token is invalid before this time |
| iat | Issued At | Unix timestamp | When the token was created |
| jti | JWT ID | String | Unique identifier for this specific token (for revocation) |
Applications typically add custom claims alongside these standard ones - things like "role", "email", "permissions", or "tenant_id". Custom claims should use namespaced names (like "https://example.com/roles") to avoid collisions.
JWT Signing Algorithms
The "alg" field in the header specifies how the signature is created. The algorithm choice affects security, performance, and key management.
| Algorithm | Type | Key | Use Case |
|---|---|---|---|
| HS256 | HMAC (symmetric) | Shared secret | Single service that both creates and verifies tokens |
| HS384 | HMAC (symmetric) | Shared secret | Same as HS256 with longer hash |
| HS512 | HMAC (symmetric) | Shared secret | Same as HS256 with longest hash |
| RS256 | RSA (asymmetric) | Private key signs, public key verifies | Multiple services verify tokens from one issuer |
| RS384 / RS512 | RSA (asymmetric) | RSA key pair | Same as RS256 with longer hash |
| ES256 | ECDSA (asymmetric) | EC key pair (P-256) | Smaller keys and signatures than RSA |
| ES384 / ES512 | ECDSA (asymmetric) | EC key pair | Same as ES256 with larger curve |
| PS256 | RSA-PSS (asymmetric) | RSA key pair | More secure padding than RS256 |
| none | No signature | None | Never use in production - allows token forgery |
Symmetric algorithms (HS*) use the same secret for signing and verification. Asymmetric algorithms (RS*, ES*, PS*) use a key pair - the private key signs and the public key verifies. Asymmetric algorithms are preferred in distributed systems where multiple services need to verify tokens without sharing a secret.
How Expiration Checking Works
This tool reads the "exp" claim (a Unix timestamp in seconds) and compares it to your system clock. It shows whether the token is currently valid, expired, or not yet valid (if "nbf" is present). The timestamps are displayed in your local timezone for easy reading.
| Scenario | Condition | Status |
|---|---|---|
| Token is fresh | Current time < exp | Valid (shows time remaining) |
| Token has expired | Current time > exp | Expired (shows how long ago) |
| No exp claim | exp is absent | No expiration set |
| Not yet valid | Current time < nbf | Not yet valid |
Common JWT lifetimes: access tokens are typically 5-60 minutes, refresh tokens 7-30 days, and ID tokens 1-24 hours. Short-lived access tokens limit the damage window if a token is compromised.
JWT Security Considerations
| Risk | Description | Mitigation |
|---|---|---|
| Token theft | JWTs are bearer tokens - whoever has the token has access | Use HTTPS, httpOnly cookies, short expiration |
| Algorithm confusion | Attacker changes alg from RS256 to HS256 and signs with the public key | Always validate the algorithm server-side, never trust the header |
| "none" algorithm | Attacker removes signature and sets alg to "none" | Reject tokens with alg "none" in your verification logic |
| Sensitive data in payload | JWTs are encoded, not encrypted - anyone can read the payload | Never put passwords, credit cards, or secrets in JWT payloads |
| No revocation | JWTs are stateless - you cannot invalidate one before it expires | Use short expiration + refresh tokens, or maintain a deny list |
| Oversized tokens | Large payloads increase every request's size | Keep payloads minimal - use IDs, not full user objects |
JWT vs Session Cookies vs API Keys
| Feature | JWT | Session Cookie | API Key |
|---|---|---|---|
| Stateless | Yes - no server-side storage | No - requires session store | Depends on implementation |
| Self-contained | Yes - claims are in the token | No - server looks up session data | No - server looks up key |
| Cross-domain | Yes (in Authorization header) | No (cookies are domain-bound) | Yes (in header or query) |
| Revocable | Not easily (stateless) | Yes (delete session server-side) | Yes (delete/disable key) |
| Size | ~800-2000 bytes typical | ~32 bytes (session ID) | ~32-64 bytes |
| Best for | APIs, microservices, SSO | Traditional web apps | Server-to-server, public APIs |
Decoding Is Not Verification
This tool decodes JWTs for inspection and debugging. It does not verify signatures because verification requires the secret key (for HMAC) or the public key (for RSA/ECDSA), and handling cryptographic keys in a browser introduces security risks. Signature verification should always happen server-side using a trusted library (jsonwebtoken for Node.js, PyJWT for Python, java-jwt for Java).
Worked Example: Decoding a Real Token
Take this sample token (shortened for readability): eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzEyMzkwNDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c. Split on the two dots and Base64URL-decode each of the first two segments. The header decodes to {"alg":"HS256","typ":"JWT"}, telling you the token is signed with HMAC-SHA256. The payload decodes to {"sub":"1234567890","name":"Jane Doe","iat":1712390400}, where iat is a Unix timestamp that maps to 6 April 2024 08:40 UTC. The third segment is the signature - a 32-byte HMAC digest encoded in Base64URL. Without the shared secret you cannot recompute or verify that digest, which is why this tool leaves the signature as-is and shows a warning banner below it.
Base64URL is not quite the same as regular Base64. RFC 4648 Section 5 swaps + for -, / for _, and drops padding = characters so the token is safe to put in URLs and HTTP headers. A correct decoder has to re-add padding before calling atob() in the browser, which is exactly what this tool does internally.
How Long Should a JWT Live?
Shorter is better. The 2024 OWASP JSON Web Token Cheat Sheet recommends access tokens of 5 to 15 minutes, refresh tokens measured in days rather than weeks, and aggressive rotation on every refresh. Real-world defaults from major identity providers are broadly consistent with that guidance.
| Provider / Spec | Access Token | Refresh Token | ID Token |
|---|---|---|---|
| Auth0 default | 24 hours (configurable) | Up to 30 days with rotation | 36,000 seconds (10 hours) |
| AWS Cognito | 1 hour (5 min to 24 h range) | 30 days (60 min to 10 years range) | 1 hour |
| Microsoft Entra ID | 60-90 min with variance | 90 days sliding, 24 hours inactive | Matches access token |
| OWASP recommendation | 5-15 minutes | Days, rotated on every use | Shortest practical |
Pair a short-lived access token with a longer refresh token and always rotate the refresh token on each use. That way a stolen access token is only useful for minutes, and a stolen refresh token only works until the next legitimate refresh invalidates it.
Common JWT Mistakes in Production
Most JWT bugs fall into a small set of patterns. If you are debugging token problems, check these before anything else.
- Trusting the
algheader. Never let the token tell the server how to verify it. Hard-code the expected algorithm in your verification call. The classicalg: nonebypass and RS256-to-HS256 algorithm confusion attacks both rely on servers readingalgfrom the token itself. - Putting secrets in the payload. Passwords, full credit card numbers, medical records, or API keys in a JWT payload are readable by anyone with the token. Payloads are encoded, not encrypted. If you need encryption use JWE (JSON Web Encryption) instead of JWS.
- Clock skew ignored. If your auth server and API server disagree on the current time by even 30 seconds, freshly issued tokens look
nbf-invalid. Most libraries support a leeway option (typically 30-60 seconds) - use it. - Missing
audchecks. Anaudclaim exists so one service can accept a token meant for it and reject tokens meant for a sibling service. Skipping the audience check lets an attacker replay a token across services. - Storing JWTs in localStorage. Any XSS on the page can read localStorage. For browser apps, httpOnly Secure cookies with SameSite=Lax or SameSite=Strict are the safer default, even though that reintroduces some of the complexity JWTs were supposed to avoid.
- No revocation plan. JWTs are stateless by design, which means you cannot invalidate one before
exp. Keep access-token lifetimes short, maintain a deny list for high-value tokens (admin sessions, password changes), and rotate refresh tokens aggressively.
Reading Specific Claims
Once decoded, the payload usually contains a mix of registered claims (from RFC 7519) and app-specific custom claims. This tool displays both in the Payload panel and highlights timestamp claims (exp, iat, nbf) in the lifetime summary. For inspecting the JSON structure in more depth, the JSON Formatter handles pretty-printing and validation. For converting between Unix epoch seconds and human time, the Unix Timestamp Converter covers both directions. And if you need to inspect the raw Base64URL segments byte-by-byte, the Base64 Encoder / Decoder can decode each part individually.
All processing happens in your browser - your tokens never leave your machine. That is especially important for JWTs because tokens are bearer credentials: anyone who holds a valid token can use it until it expires. Paste with confidence, but still treat production tokens as sensitive the way you would a password.
Sources
Frequently Asked Questions
What is a JWT and what are its three parts?
A JSON Web Token (JWT) consists of three Base64URL-encoded parts separated by dots. The header specifies the signing algorithm, the payload contains the claims (data), and the signature is used to verify the token's integrity. This tool decodes the header and payload so you can inspect the claims inside any JWT.
Can this tool verify JWT signatures?
No. Signature verification requires the secret key or public key used to sign the token, which cannot be safely handled in a browser. This tool decodes and displays the token contents for inspection and debugging purposes only. For production signature verification, use a server-side library.
Is it safe to paste my JWT into this tool?
Yes. All decoding happens entirely in your browser using JavaScript. Your token is never transmitted to any server. However, you should still avoid sharing JWTs publicly since they may contain sensitive claims such as user IDs or permissions.
How do I check if a JWT has expired?
After decoding, the tool reads the "exp" (expiration) claim from the payload and compares it to the current time. It displays whether the token is still valid or has expired, along with the exact expiration date and how much time remains or has passed since expiry.
Related Tools
Link to this tool
Copy this HTML to link to this tool from your website or blog.
<a href="https://toolboxkit.io/tools/jwt-decoder/" title="JWT Decoder - Free Online Tool">Try JWT Decoder on ToolboxKit.io</a>