JWT Decoder
Paste a token on the left, or load the example.
| Claim | Value |
|---|
No claims to read: the payload is not a JSON object.
About the decoder
Your document never leaves the browser.
jwt decoder · decode · verify · nothing leaves the browser
Paste a token to read its header and payload, see its claims with real times, and check its signature against a secret or a public key — in this tab, with nothing sent, stored or put in the address. Want to work on the payload itself? Open payload in the editor, or open the JSON editor and paste it there.
Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1LTEyMyIsIm5hbWUiOiJBZGEiLCJpYXQiOjE3MDAwMDAwMDAsImV4cCI6MTcwMDAwMzYwMH0.bm90LWEtcmVhbC1zaWduYXR1cmUHeader
{
"alg": "HS256",
"typ": "JWT"
}Payload
{
"sub": "u-123",
"name": "Ada",
"iat": 1700000000,
"exp": 1700003600
}A JSON Web Token in its usual compact form is three pieces of base64url joined by dots. The first is a small JSON header naming the signing algorithm, the second is the payload of claims about a user or a session, and the third is the signature over the first two. The field above colours the three so you can see where each starts, and the Bearer prefix copied out of an Authorization header along with the token is stripped for you.
The thing most worth knowing is that the first two parts are encoded and not encrypted. Anyone who holds the token can read every claim in it, which is exactly what this page does, with no key at all, so never put a secret in a payload. And reading a token proves nothing about it: a forged token decodes as happily as a genuine one, and only the signature, checked against a key you trust, tells the two apart.
The Verify card takes the algorithm from the header and checks the signature with the Web Crypto API built into the browser. Thirteen algorithms are supported: HS256, HS384 and HS512 with a shared secret; RS256, RS384 and RS512, and the PSS variants PS256, PS384 and PS512, with an RSA public key; ES256, ES384 and ES512 with a P-256, P-384 or P-521 key; and EdDSA with an Ed25519 key.
For an HS token, paste the secret as text, or tick Secret is base64url when your configuration stores it that way. For the others, paste the public key as a PEM block (PUBLIC KEY or RSA PUBLIC KEY), as the X.509 certificate that carries it, as a JWK, or as a whole JWKS from your provider’s jwks_uri, from which the key whose kid matches the header is chosen. A certificate is used for its key only; its dates and its issuer are not checked. The answer is live: it updates as you type, and reads Signature verified, Invalid signature, Not signed, Can't verify or Key problem, with the key the page used named beside it.
Token
eyJhbGciOiJub25lIn0.eyJzdWIiOiJBZGEifQ.Reported
Not signed
This token declares alg "none", so it has no signature to verify.The best-known JWT flaw is simple. A server that verifies RS256 tokens holds a public key, and public keys are public. If an attacker changes the header to HS256 and signs a forged payload with HMAC, using the public key’s bytes as the secret, a careless verifier that lets the token choose its own algorithm will compute the same HMAC and accept the forgery.
This page will not do that. The algorithm comes from the header, but the key has to be the kind that algorithm uses, so an HS token checked against an RSA or EC public key is refused as a Key problem whose message ends Verifying an HMAC token with a public key is the 'algorithm confusion' attack, so it is refused. A JWK that declares an alg of its own which differs from the header’s is refused as well.
The header may carry a key of its own: a jwk member, a certificate chain in x5c, or a link to one in jku or x5u. A verifier that trusts those has let the token vouch for itself, since whoever forged the token chose the key too. They are shown in the header like any other member and never used to verify, and a notice says so: The header carries its own key. It is not used to verify, since a token cannot vouch for itself. Following jku or x5u would also mean fetching a URL, and this page makes no requests.
RFC 7518 asks for an HMAC secret at least as long as the hash, 32 bytes for HS256 (§3.2), and for an RSA modulus of at least 2,048 bits (§3.3). A key below either line is still used, since this is a tool for reading tokens and not a gate, but the verdict comes with a notice such as The HMAC secret is 19 bytes; HS256 recommends at least 32. That is the notice the Example button shows, because the secret every JWT tutorial uses is shorter than its own algorithm recommends.
Token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1LTEyMyIsImlhdCI6MTcwMDAwMDAwMCwibmJmIjoxNzAwMDAwNDAwLCJleHAiOjE3MDAwMDM2MDB9.aW52ZW50ZWQtc2lnbmF0dXJlRead at 2023-11-14 22:30 UTC
Active, expires in 43 minutes
iat · Issued at · 2023-11-14T22:13:20Z · 16 minutes ago
nbf · Not before · 2023-11-14T22:20:00Z · 10 minutes ago
exp · Expires · 2023-11-14T23:13:20Z · in 43 minutesThe example reads the token at 2023-11-14 22:30 UTC, so its relative times stay exact.
The Claims card lists every member of the payload, and names the registered ones and the OpenID Connect ones. The times, exp, nbf, iat and auth_time among them, are shown in UTC to the second with how long ago or how far off each is; hover one to see it in your own time zone. Above the table a status line gives the verdict on the times in one of four shapes, such as Expired 3 hours ago, Not valid until a stated time, Active, expires in 12 minutes, or No expiry: the token has no exp claim. It keeps itself current while the tab is open.
No clock skew is allowed. Servers often accept a token for a minute or two after its exp, to forgive clocks that disagree, but that allowance is your server’s setting, not a property of the token, so this page reports the plain arithmetic and leaves the leeway to you. A claim that breaks its own rules, an iat in the future or an iss that is not a string, is marked in the table in its own words.
Token
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..aW52ZW50ZWQtaXY.aW52ZW50ZWQtY2lwaGVydGV4dA.aW52ZW50ZWQtdGFnReported
Encrypted (JWE): only the header can be readA token with five parts rather than three is a JWE, an encrypted token. Its header is plain base64url and is shown in full, naming the key-management and content-encryption algorithms. Everything else is ciphertext, and without the recipient’s private key there is nothing more to read.
A token is a credential: whoever holds an unexpired one can usually act as its owner. So the token and the key you paste are held only in this tab’s memory. They are not written to local or session storage, not placed in the address, not added to your history, and a link cannot arrive with a token already filled in. Reload, and both fields are empty again. Two things fill them for you: Try it in the decoder on a Guide page, and Open in JWT decoder in the editor’s status bar when a pane holds nothing but a token. Each hands its token across through the session storage of the tab you pressed it in, where the decoder reads it once and deletes it, so no link from anywhere else can do the same.
There is one exception, and it is yours to trigger. Open payload in the editor hands the decoded payload, never the token or the key, to the JSON editor through a one-shot record in this tab’s session storage, which the editor reads and deletes as it opens. From there you can see the claims as a tree, a table or a graph, or check their shape against a contract on the JSON Schema validator.
Never paste a production private key here or into any web page. You only need the public half to verify, and if you paste a private key by mistake the page uses its public half and warns you in the engine’s own words: Never paste a private key into a web page; only the public key is needed to verify.
No. Decoding is base64url and a JSON parse, and verifying uses the Web Crypto API that every current browser ships, so both happen on your own machine and the page makes no request while you use it.
Because the token is one this page can read but cannot check. An encrypted token (JWE) is the usual reason, and the detail line then reads Encrypted tokens (JWE) can't be verified here, only decoded. The others are an algorithm outside the thirteen listed above, a header that marks a parameter as critical which the page does not understand, the rare unencoded-payload form, and a browser too old to offer Ed25519. Each one is named in the detail line under the title.
HS256 is checked with a shared secret, and an RSA key is a public key. Using the bytes of a public key as an HMAC secret is exactly the forgery described in the algorithm confusion section, so the page reports Key problem and names the attack rather than computing a result. Paste the secret the token was signed with, or check which algorithm your issuer really uses.
No. A token that decodes cleanly was merely well-formed; anybody can write a header and a payload and base64url them. Validity needs the signature to check out against the right key, and then the times, the issuer and the audience to be ones your service accepts.
No, and on purpose. Signing needs the private key or the shared secret, and a web page is the wrong place to type either. Mint tokens in your own code or your identity provider, and bring them here to be read.