How to decode a JWT token online
jsonsql.dev decodes JSON Web Tokens instantly in your browser. No data is sent to any server — your token stays on your machine.
Paste your JWT — copy the JWT from your API response, Authorization header, or cookie and paste it into the input field above. The "Bearer " prefix is stripped automatically.
View decoded parts — the header, payload, and signature are displayed immediately. Claims like exp, iat, and sub are shown in human-readable format.
Copy what you need — click Copy on the header or payload section to copy the decoded JSON to your clipboard.
Example
Input JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cDecoded header:
{
"alg": "HS256",
"typ": "JWT"
}Decoded payload:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}What is a JWT?
A JSON Web Token (JWT) is a compact, URL-safe token format used for securely transmitting information between parties. It consists of three Base64URL-encoded parts separated by dots: header, payload, and signature.
The header specifies the signing algorithm (e.g., HS256, RS256). The payload contains claims — statements about the user and metadata. The signature verifies the token has not been tampered with.
Common JWT claims
iss(Issuer) — who issued the tokensub(Subject) — the user or entity the token representsaud(Audience) — intended recipient of the tokenexp(Expiration) — Unix timestamp when the token expiresnbf(Not Before) — token is not valid before this timeiat(Issued At) — when the token was createdjti(JWT ID) — unique identifier for the token
Features
- Decode JWT header and payload to formatted JSON
- Color-coded token parts: header (red), payload (purple), signature (cyan)
- Human-readable display of common claims (iss, sub, aud, exp, nbf, iat, jti)
- Expiration status: shows if the token is expired or when it expires
- Syntax highlighting for decoded JSON
- Automatically strips "Bearer " prefix from pasted tokens
- Copy header or payload individually
- Dark and light theme support
- Works offline — no internet needed after the page loads
- 100% client-side — no data is sent to any server
JWT Decoder vs other tools
| Feature | jsonsql.dev | jwt.io | jwt.ms |
|---|---|---|---|
| Client-side only | Yes | Yes | Yes |
| Color-coded parts | Yes | Yes | No |
| Expiration status | Yes | No | Yes |
| Claims explanation | Yes | No | Yes |
| Syntax highlighting | Yes | Yes | No |
| Dark mode | Yes | No | No |
| No ads | Yes | No | Yes |
| Works offline | Yes | No | No |
JWT structure explained
A JWT consists of three Base64URL-encoded parts separated by dots: the header (algorithm and type), the payload (claims about the user), and the signature (cryptographic proof of authenticity).
Header
The header is a JSON object that describes the token's type and the cryptographic algorithm used to sign it. The two standard fields are:
alg— the signing algorithm. Common values: HS256 (HMAC with SHA-256), RS256 (RSA with SHA-256), ES256 (ECDSA with P-256 curve). HS256 uses a shared secret; RS256 and ES256 use public/private key pairs.typ— the token type, almost always"JWT".
{
"alg": "RS256",
"typ": "JWT",
"kid": "my-key-id"
}Some headers include a kid (Key ID) field that tells the server which key to use for signature verification — useful when rotating keys.
Payload
The payload contains claims — statements about the user and metadata. Claims fall into three categories:
- Registered claims — standardized by RFC 7519:
iss(issuer),sub(subject),aud(audience),exp(expiration),nbf(not before),iat(issued at),jti(JWT ID). - Public claims — defined in the IANA JSON Web Token Claims registry or using collision-resistant names (e.g., URIs). Examples:
email,name,preferred_username. - Private claims — custom claims agreed upon between the issuer and consumer, such as
role,tenant_id, orpermissions.
{
"iss": "https://auth.example.com",
"sub": "user-42",
"aud": "https://api.example.com",
"exp": 1893456000,
"iat": 1672531200,
"role": "admin",
"permissions": ["read", "write"]
}Signature
The signature ensures the token has not been tampered with. It is computed by:
- Concatenating the Base64URL-encoded header and payload with a dot:
base64url(header) + "." + base64url(payload) - Signing the result with the specified algorithm:
- HMAC (HS256/HS384/HS512):
HMAC-SHA(secret, data)— uses a single shared secret key. - RSA (RS256/RS384/RS512):
RSA-SHA(privateKey, data)— signs with a private key, verified with the corresponding public key. - ECDSA (ES256/ES384/ES512):
ECDSA-SHA(privateKey, data)— elliptic curve variant, smaller keys than RSA for equivalent security.
- HMAC (HS256/HS384/HS512):
- Base64URL-encoding the resulting bytes to produce the third part of the token.
The signature proves the token was issued by a trusted party and has not been modified. Without the signing key, you cannot create a valid signature — but anyone can decode the header and payload.
Common JWT claims reference
| Claim | Name | Meaning | Example value | Common usage |
|---|---|---|---|---|
iss | Issuer | Identifies the principal that issued the token | "https://auth.example.com" | Verify token origin; reject tokens from unknown issuers |
sub | Subject | Identifies the user or entity the token represents | "user-42" | Map token to a specific user account in your system |
aud | Audience | Intended recipient(s) of the token | "https://api.example.com" | Prevent token misuse across different services |
exp | Expiration | Unix timestamp after which the token must be rejected | 1893456000 (2030-01-01) | Enforce token lifetime; reject expired tokens even if signature is valid |
nbf | Not Before | Unix timestamp before which the token must not be accepted | 1672531200 (2023-01-01) | Delay token activation; useful for pre-issued tokens |
iat | Issued At | Unix timestamp when the token was created | 1672531200 (2023-01-01) | Determine token age; enforce maximum age policies |
jti | JWT ID | Unique identifier for the token | "550e8400-e29b-41d4-a716" | Prevent token replay attacks by tracking used token IDs |
The exp claim is a Unix timestamp indicating when the token expires. Tokens should be rejected after this time, even if the signature is valid. Most JWT libraries handle this automatically, but clock skew between servers can cause issues — a common tolerance is 30-60 seconds.
JWT security best practices
JWT payloads are Base64URL-encoded, not encrypted — anyone can decode and read them. Never store passwords, credit card numbers, or other secrets in a JWT.
- Never store sensitive data in the payload. The payload is only encoded, not encrypted. Anyone who intercepts the token can read every claim. If you need to transmit sensitive data, use JWE (JSON Web Encryption) instead of JWS.
- Always verify signatures server-side. Decoding a JWT and trusting its claims without verifying the signature is a critical vulnerability. An attacker could modify the payload and forge claims like
"role": "admin". - Use short expiration times. Access tokens should expire in 5-15 minutes. Use refresh tokens (stored securely, ideally in httpOnly cookies) to obtain new access tokens. Short-lived tokens limit the damage window if a token is compromised.
- Reject the "none" algorithm. Some JWT libraries have historically accepted
"alg": "none", which means no signature is required. Always validate the algorithm against an allowlist of expected values. - Use asymmetric algorithms for distributed systems. RS256 or ES256 let services verify tokens with a public key without needing access to the signing secret. This is essential for microservices architectures.
- Understand decoding vs. verifying. Decoding extracts header and payload from the Base64URL-encoded token — anyone can do this, no key required. Verifying checks the cryptographic signature to ensure the token was not tampered with and was issued by a trusted party. This tool only decodes; always verify server-side.
JWT debugging workflow
When a JWT-related issue arises in your application, follow this systematic debugging workflow:
- Get the token from your browser. Open Chrome DevTools (F12), then:
- From cookies: Go to Application tab, expand Cookies in the sidebar, and find the cookie containing your JWT.
- From localStorage/sessionStorage: Go to Application tab, expand Local Storage or Session Storage, and look for keys like
access_tokenorid_token. - From a network request: Go to Network tab, find an API request, click it, and look for the
Authorization: Bearer eyJ...header.
- Paste the token into the decoder. Copy the full token (or the entire
Bearer eyJ...string — the prefix is stripped automatically) and paste it into the input field above. - Check the expiration. Look at the expiration badge next to the Payload header. If it says "Expired X ago", the token has expired and needs to be refreshed. Compare the
expandiattimestamps to understand the token's intended lifetime. - Verify the claims. Check that
issmatches your expected issuer,audmatches your API, andsubis the correct user. Mismatched claims are a common cause of 401/403 errors. - Check the algorithm. Ensure the
algin the header matches what your server expects. A mismatch (e.g., sending an HS256 token to a server expecting RS256) will cause signature verification to fail.
Common issues and fixes:
- Expired token — refresh the token using your refresh token endpoint or re-authenticate.
- Wrong audience (
aud) — ensure the token was issued for the correct API. Multi-tenant systems often have different audience values per environment. - Clock skew — if tokens expire immediately after being issued, check that server clocks are synchronized (NTP). Most libraries allow a small leeway (30-60 seconds).
- Invalid signature — the token may have been tampered with, or the server is using a different signing key than expected. Check key rotation settings.
JWT vs session cookies vs API keys
Different authentication mechanisms suit different architectures. Here is how JWT compares to traditional session cookies and API keys:
| Feature | JWT | Session cookies | API keys |
|---|---|---|---|
| State | Stateless — all data in the token | Stateful — session data on the server | Stateless — key identifies the client |
| Scalability | Excellent — no server-side storage needed | Requires shared session store (Redis, DB) across servers | Excellent — simple lookup |
| Revocation | Hard — must use blocklists or short expiry | Easy — delete session from server | Easy — delete key from database |
| Payload | Contains user data and claims | Session ID only — data on server | No payload — just an identifier |
| Cross-domain | Works easily via Authorization header | Requires CORS + SameSite configuration | Works via header or query parameter |
| Security risk | Token theft gives access until expiry | Session hijacking, CSRF attacks | Key leakage gives permanent access |
| Best for | SPAs, mobile apps, microservices | Traditional server-rendered web apps | Server-to-server, third-party integrations |
| Token size | Large (hundreds of bytes to several KB) | Small (session ID, ~32 bytes) | Small (~32-64 bytes) |
When to use which: Use JWTs for stateless authentication in SPAs and microservices where horizontal scaling matters. Use session cookies for server-rendered applications where easy revocation is important. Use API keys for server-to-server communication and third-party API access where user context is not needed.
Related tools
Frequently asked questions
What are the three parts of a JWT?
A JWT has three Base64URL-encoded parts separated by dots: the header (algorithm and token type), the payload (claims like user ID, expiration, etc.), and the signature (cryptographic proof of integrity).
What is the difference between decoding and verifying a JWT?
Decoding extracts the header and payload from the Base64URL-encoded token — anyone can do this without a key. Verifying checks the signature to confirm the token was not tampered with, which requires the signing key.
How do I check if a JWT token is expired?
Decode the token and look at the exp (expiration) claim in the payload. It is a Unix timestamp in seconds. If the current time is past that timestamp, the token is expired. This tool automatically shows the expiration status with a colored badge — green for valid, red for expired — along with a human-readable time difference.
What is the difference between HS256 and RS256?
HS256 (HMAC with SHA-256) uses a single shared secret key for both signing and verification. Both the issuer and verifier must know the same secret. RS256 (RSA with SHA-256) uses a public/private key pair — the issuer signs with the private key, and verifiers use the public key. RS256 is preferred for distributed systems because verifiers do not need access to the signing secret.
Does this work with JWE (encrypted tokens)?
No. This tool decodes JWS (signed) tokens only. JWE tokens are encrypted and cannot be decoded without the decryption key.
Can a JWT be tampered with?
Anyone can modify the Base64URL-encoded payload of a JWT, but the signature will no longer be valid. A properly implemented server will reject a token with a mismatched signature. The risk arises when servers fail to verify signatures, accept the "none" algorithm, or confuse symmetric and asymmetric keys. Always verify signatures server-side with a trusted library.