JWT Decoder

Paste a JSON Web Token to read its header, claims and expiry, then check its signature with a secret or public key. Everything happens in this tab — the token is never sent anywhere.

    Header

    
              

    Payload

    
              
    ClaimValueMeaning

    Verify signature

    What is inside a JWT

    A JSON Web Token, defined in RFC 7519, is three pieces of text joined by dots: a header, a payload and a signature. The first two are JSON objects encoded with Base64url — ordinary Base64 with - and _ in place of + and /, and the trailing = padding dropped (RFC 7515, section 2). That is why every JWT starts with eyJ: it is what {" looks like once encoded.

    • Header — how the token is protected. alg names the signing algorithm; typ is usually JWT; kid says which of the issuer's keys was used.
    • Payload — the claims: who the token is about, who issued it, who it is for, and when it stops being valid, plus whatever the application adds (roles, scopes, an email address).
    • Signature — computed over the first two parts exactly as they appear, dot included. Change one character of the header or payload and it no longer matches.

    The important consequence: a JWT is encoded, not encrypted. Anyone holding one can read every claim in it, exactly as this page does. Nothing secret belongs in a payload unless the token is also encrypted (a JWE, which has five parts — more on that below).

    Decoding is not verifying

    Reading a token tells you what it claims. It says nothing about whether those claims are true, because anyone can write a header and a payload and encode them. What makes a JWT trustworthy is the signature, and that can only be checked with the right key:

    • For HS256, HS384, HS512 (HMAC), the same shared secret that signed the token. Paste it into the Secret field. If the issuer stores the secret Base64-encoded, tick the box so it is decoded to raw bytes first — a mismatch here is the most common reason a correct secret “fails”.
    • For RS*, PS* and ES*, the issuer's public key, as a PEM block or a JWK. Paste a whole JWK Set and the tool picks the key whose kid matches the header.

    The check runs with your browser's built-in WebCrypto, the same primitives a server library would use. A green result means the signature matches that key. It does not mean the token should be accepted — your server still has to check expiry, issuer and audience, and whether it trusts that key in the first place.

    The registered claims

    RFC 7519 reserves seven claim names. None is mandatory, but when they appear they mean this:

    ClaimNameWhat it says
    issIssuerWho created and signed the token, often the identity provider's URL
    subSubjectWho the token is about — usually a user id
    audAudienceWho the token is meant for; a string or an array. A service should reject tokens not addressed to it
    expExpiration timeOn or after this moment the token must not be accepted
    nbfNot beforeBefore this moment the token must not be accepted
    iatIssued atWhen the token was created
    jtiJWT IDA unique id, used to stop a token being replayed or to revoke one

    Reading exp, nbf and iat

    All three are a NumericDate: the number of seconds since 1 January 1970 UTC. The decoder converts each to a UTC date, your local time and a “3 hours ago” style offset, and puts a status line at the top saying whether the token is inside its window right now.

    Two things catch people out. First, a 13-digit value is milliseconds, not seconds — JavaScript's Date.now() leaks into the token and the expiry lands tens of thousands of years in the future. The decoder flags that. Second, servers are allowed a little slack: RFC 7519 lets implementations add “some small leeway, usually no more than a few minutes” for clock skew, so a token a minute past exp may still be accepted by one service and refused by another.

    Which algorithm is which

    algTypeVerify withSupported here
    HS256 / HS384 / HS512HMAC with SHA-2The shared secretYes
    RS256 / RS384 / RS512RSA PKCS#1 v1.5RSA public keyYes
    PS256 / PS384 / PS512RSA-PSSRSA public keyYes
    ES256 / ES384 / ES512ECDSA on P-256 / P-384 / P-521EC public keyYes
    EdDSAEd25519OKP public keyWhere your browser supports Ed25519 in WebCrypto
    noneUnsecuredNothing — there is no signatureDecoded and flagged

    The practical difference between the families: with HS256 one secret both signs and verifies, so every service that can check a token can also mint one. With RS256, PS256 or ES256 only the issuer holds the private key and everyone else verifies with the public half. As soon as more than one service reads your tokens, the asymmetric algorithms are the safer default.

    Mistakes the decoder will point out

    RFC 8725, the IETF's best-practice document for JWTs, lists the attacks that keep working in the wild. Three are visible from the token alone, so the decoder flags them:

    • "alg": "none". An unsecured token with an empty signature. Libraries that honour whatever the header says have accepted these as valid. A server should decide which algorithms it accepts, never read that decision from the token.
    • RS256 swapped for HS256. If a server trusts the header's alg and hands its RSA public key to an HMAC check, an attacker can sign tokens with that public key as the secret. When you verify an HS token here with something that looks like a PEM key, the tool warns you, because that is exactly this confusion.
    • Weak HMAC secrets. RFC 8725 says human-memorable passwords must not be used directly as HMAC keys: an HS256 token plus a guessable secret can be cracked offline. Use at least 32 random bytes.

    It also notes tokens with no exp at all, timestamps in milliseconds, and segments written in standard Base64 (+, /, =) instead of Base64url — those still decode here, but a strict library will reject them.

    Is it safe to paste a token here?

    This page has no backend. The token is decoded by JavaScript in the tab and the signature is checked by the browser's WebCrypto, so neither the token nor your key is transmitted, logged or stored — reload the page and both are gone. You can confirm it yourself in the browser's developer tools: the Network tab shows no request when you paste or verify.

    Even so, treat a live access token as what it is: a credential that works until it expires. The habit worth keeping on any website is to decode expired or test tokens and to never paste a production signing secret or private key anywhere you do not control.

    What this tool cannot do

    • Decrypt a JWE. An encrypted token has five parts and a ciphertext payload (RFC 7516). The decoder recognises one, shows the readable header — which names the alg and enc used — and stops there.
    • Fetch keys for you. It does not download a JWK Set from a jku or jwks_uri URL. Open that URL yourself and paste the JSON.
    • Read certificates or PKCS#1 keys. PEM must be an SPKI public key (BEGIN PUBLIC KEY). A BEGIN CERTIFICATE or BEGIN RSA PUBLIC KEY block needs converting first, for example with openssl x509 -pubkey -noout or openssl rsa -RSAPublicKey_in -pubout.
    • Tell you whether a token is revoked, or whether a server would accept it. That depends on the server's own rules, leeway and revocation list.
    • Create or sign tokens. It reads and checks; it does not issue.

    How to use it

    Paste a token into the box — with or without a leading Bearer . The coloured strip shows the three parts, the status line reports the validity window, and the header and payload appear as formatted JSON with a table explaining each registered claim. To check the signature, fill in the secret or public key below and press Verify. The two example buttons load real signed tokens so you can see a passing check: the HS256 example's secret is sigmawire-demo-secret, and the RS256 example loads its public key for you.

    Related tools: to inspect an arbitrary Base64 string use the Base64 encoder and decoder; to tidy a large payload use the JSON formatter; for a random jti, the UUID generator.

    Questions

    Is it safe to paste a JWT into this decoder?

    The page decodes and verifies in your browser and makes no network request containing the token or the key, so nothing leaves the tab. The general caution still applies: a live access token is a credential, so prefer expired or test tokens on any website, and never paste a production signing secret into one.

    Does decoding a JWT prove it is genuine?

    No. The header and payload are only Base64url-encoded, so anyone can read them and anyone can write new ones. Only a successful signature check with the right key shows the token was issued by the holder of that key and has not been altered.

    Why does my token show as expired when it still works?

    Servers are allowed a small leeway for clock skew; RFC 7519 says usually no more than a few minutes. Some also cache a validation result. Check the exp value itself: it is seconds since 1 January 1970 UTC. If it has 13 digits it is in milliseconds, which is a bug in whatever issued it.

    Can this tool decrypt an encrypted JWT (JWE)?

    No. An encrypted token has five parts instead of three and its payload is ciphertext. The tool detects that and shows the readable header, which names the key-management and content-encryption algorithms, but decrypting needs the private key and is not offered here.

    What is the difference between HS256 and RS256?

    HS256 is an HMAC: one shared secret both signs and verifies, so every service that verifies can also mint tokens. RS256 is an RSA signature: a private key signs and a public key verifies, so verifiers cannot forge tokens. Use an asymmetric algorithm when more than one party needs to check tokens.

    Where do I find the public key to verify a token?

    Most identity providers publish their keys as a JWK Set, usually linked from the jwks_uri field of their OpenID configuration document. Copy the key whose kid matches the kid in the token header, or paste the whole set and the tool picks the matching key.