JWT Decoder

Runs locally

Decode a JSON Web Token, check its expiry and verify its signature — in your browser.

Token

Paste the token, a whole Authorization header or a quoted string — the extras are removed.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImRlbW8tMjAyNiJ9.eyJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20vIiwic3ViIjoidXNlcl84ZjNhMjEiLCJhdWQiOiJhcGkuZXhhbXBsZS5jb20iLCJuYW1lIjoiQWRhIExvdmVsYWNlIiwic2NvcGUiOiJyZWFkOm9yZGVycyB3cml0ZTpvcmRlcnMiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoyNTU2MDU3NjAwLCJqdGkiOiJiN2UxYzBkMi0zZjRhLTRjNWItOWU2Zi0xYTJiM2M0ZDVlNmYifQ.otbxfUvjHMFX5e0-t7Nfxc87fKQhYUDlTBVBn7oYD5E
Expiry
Checking against your clock…
Not before
No nbf claim
Algorithm
HS256
Signature
Not verified yet — add the key below.

Header

{
"alg": "HS256",
"typ": "JWT",
"kid": "demo-2026"
}

Payload

{
"iss": "https://auth.example.com/",
"sub": "user_8f3a21",
"aud": "api.example.com",
"name": "Ada Lovelace",
"scope": "read:orders write:orders",
"iat": 1767225600,
"nbf": 1767225600,
"exp": 2556057600,
"jti": "b7e1c0d2-3f4a-4c5b-9e6f-1a2b3c4d5e6f"
}

Claims

What each field means. Times are shown in UTC; JWT times are seconds since 1970.

ClaimValueMeaning
alg · headerHS256Algorithm. How the signature was made; "none" means unsigned
typ · headerJWTType. Media type of the token, usually JWT or at+jwt
kid · headerdemo-2026Key ID. Which key in the issuer’s JWKS signed this token
isshttps://auth.example.com/Issuer. Who created and signed the token — usually the identity provider’s URL
subuser_8f3a21Subject. Whom the token is about: a user or client ID, unique within the issuer
audapi.example.comAudience. Which API or app the token is meant for; a resource server must reject other audiences
nameAda LovelaceName. The user’s full name
scoperead:orders write:ordersScope. Space-separated permissions granted (OAuth 2.0)
iat1767225600
2026-01-01T00:00:00Z
Issued at. When the token was created
nbf1767225600
2026-01-01T00:00:00Z
Not before. Before this instant the token must be rejected
exp2556057600
2050-12-31T00:00:00Z
Expiration time. After this instant the token must be rejected
jtib7e1c0d2-3f4a-4c5b-9e6f-1a2b3c4d5e6fJWT ID. A unique ID, used to stop the same token being replayed

Verify the signature

Algorithm from the header: HS256 · kid "demo-2026". Verified with Web Crypto in this tab; the key never leaves it.

Guide

Decoding a token is not the same as trusting it

A JSON Web Token (RFC 7519) is three Base64URL segments joined by dots: a header naming the algorithm, a payload of claims, and a signature over the first two. The header and payload are only encoded, so anyone holding the token can read them — never put secrets in a payload. Decoding shows what the issuer claimed; the signature is what proves the issuer actually said it and that nobody changed a byte since.

Verification here runs on Web Crypto without leaving the page. For HS256, HS384 and HS512 the key is a shared secret; tick the Base64 box when your provider hands the secret out encoded, as Auth0 and many others do. For RS, PS and ES algorithms paste the public key as a PEM, a certificate, a JWK, or the whole JWKS from the issuer’s /.well-known/jwks.json, and the key is chosen by the token’s kid. The page never fetches a JWKS itself — a token can name a jku URL, and a verifier that follows it lets the attacker choose the key. To make a token to test against, sign one with the JWT encoder.

Time claims are seconds since 1970. The countdown uses your device’s clock, and a token whose nbf is a few seconds in the future usually means the issuer’s clock is ahead, not that the token is bad; most libraries accept 30 to 60 seconds of leeway. A 13-digit exp is a common bug — milliseconds written where seconds belong — and is flagged, because it makes a token look valid for more than 50,000 years. The Timestamp Converter shows any claim in other time zones.

Token (HS256, secret "your-256-bit-secret")

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Decoded

Header   {"alg":"HS256","typ":"JWT"}
Payload  {"sub":"1234567890","name":"John Doe",
          "iat":1516239022}
iat      2018-01-18T01:30:22Z
exp      none — this token never expires
Signature verified with the secret

The well-known example token. Change one character of the payload and verification fails, while decoding still works — which is exactly why decoding alone proves nothing.

Where people get caught

Trusting a decoded token

Any client can build a token with admin: true. A server must verify the signature and check exp, nbf, iss and aud before using a single claim.

alg: none and algorithm confusion

Reject unsigned tokens, and fix the expected algorithm per key. Libraries that let the token pick HS256 with an RSA public key as the "secret" have been exploited.

A Base64-encoded secret used as text

If the provider shows the secret Base64-encoded, the signing key is the decoded bytes. Using the string itself produces a different signature and a confusing "invalid signature".

exp in milliseconds

Date.now() is milliseconds; JWT NumericDate is seconds. An exp of 1767229200000 means the year 57,971, so the token effectively never expires.

Pasting the whole header

Authorization: Bearer eyJ… is not a token. This page strips the prefix and quotes and says so; your own code needs to do the same before verifying.

About JSON Web Tokens

How it works in 4 steps · 4 common use cases · 5 questions answered

How it works

  1. 1.Paste a token or an Authorization header; prefixes, quotes and line breaks are removed.
  2. 2.Read the header and payload, with each claim explained and times converted.
  3. 3.Watch the expiry countdown and the nbf and iat checks.
  4. 4.Paste a secret, PEM, JWK or JWKS to verify the signature locally.

Common use cases

  • •Finding out why an API returns 401 for a token
  • •Checking the scopes, audience and expiry an identity provider issued
  • •Verifying a webhook or service-to-service token against a public key
  • •Debugging clock skew between an issuer and an API

FAQ

Is it safe to paste a production token here?

The token, secret and keys stay in this tab: decoding and verification run locally with Web Crypto and nothing is sent over the network. A token is still a credential, so treat the screen like any other place it appears.

Can this page verify a JWT signature?

Yes, for HS256/384/512 with a secret (plain or Base64), RS256/384/512 and PS256/384/512 with an RSA key, ES256/384/512 with an EC key, and EdDSA where the browser supports Ed25519.

Why is my token valid here but rejected by the server?

The server also checks the audience, the issuer, the expected algorithm and the key. A mismatch in aud or iss, a rotated key or a clock-skew nbf are the usual causes.

Why won’t it fetch the JWKS for me?

Fetching would send a request from this page, and a token-supplied jku URL is exactly what an attacker controls. Open the issuer’s jwks.json yourself and paste it.

Can it decode an encrypted token (JWE)?

No. A JWE has five parts and its payload is encrypted for the recipient. The page recognises one and shows the header, which is not encrypted.