Scrawlspace › Developer Utilities

JWT Decoder, Encoder & Verifier

Paste a JSON Web Token to decode its header and claims, see whether it has expired, and verify its signature with a secret, PEM key, JWK or JWKS. It handles HS, RS, PS, ES and EdDSA tokens and flags unsigned (alg: none) and encrypted (JWE) ones. Switch to Encode / Sign to create a signed token from your own header and payload, with a secret, a private key, or a key pair generated on the spot. Everything runs in your browser with the Web Crypto API, and this tool doesn't send your token, secret or key anywhere.

How to use JWT Decoder & Encoder

  1. To decode, stay on Decode / Verify and paste a JWT into the Encoded token box, or click Sample. A leading "Bearer " is ignored.
  2. Read the decoded Header, Payload and Claims. Dates such as exp, iat and nbf are shown as local times, and a badge says Not expired, Expired, Not valid yet or No expiry. Copy JSON copies the header and payload for the JSON viewer.
  3. To verify, enter the shared secret for HS256/384/512 (tick Secret is Base64 encoded if it is), or paste a public key as PEM, JWK or JWKS for RS, PS, ES and EdDSA.
  4. To create a token, switch to Encode / Sign, choose the Algorithm and edit the Header and Payload JSON. The iat = now and exp +1 hour, +1 day and +7 days buttons set the times.
  5. Enter a secret or click Generate a secret for HS algorithms, or paste a private key (PKCS#8 PEM or JWK) or click Generate a key pair for the others. The signed token updates as you type: Copy token, or click Verify in decoder to check it with its secret or public key.

Frequently asked questions

What is a JWT?

A JSON Web Token (RFC 7519) is a compact way to pass claims, such as who a user is and when access expires. Most JWTs are signed (JWS): three Base64URL parts, header.payload.signature, joined by dots. An unsigned token has alg: none and an empty third part. An encrypted JWT (JWE) has five parts and can't be read without the decryption key; this tool recognises one and says so.

Can anyone read the data in a JWT?

In a signed JWT, yes. The payload is only Base64URL-encoded, not encrypted, so anyone holding the token can decode it without the secret or key; those are needed only to verify the signature. Never put secrets or sensitive personal data in a payload. Only a JWE keeps its payload private.

What does a valid signature prove?

That the header and payload haven't been changed since signing, and that the token was signed by someone holding the key. With RS, PS, ES or EdDSA that is the holder of the private key, normally the issuer. With HS256 it is anyone who has the shared secret, so every service that can verify an HS256 token can also forge one. A signature does not check expiry or audience: your server must still check exp, nbf, iss and aud.

How do I check if a JWT has expired?

Paste it in and look at the badge above the header and at the exp row under Claims. exp is a Unix time in seconds, shown as a local date with how long ago or from now it is. To convert one by hand, use the Unix timestamp converter. The Not expired badge only compares exp and nbf with your clock; whether the signature is good is shown separately under the key box.

How do I create a JWT?

Switch to Encode / Sign. Pick an algorithm, edit the header and payload as JSON (they start with alg, typ, sub, name, iat set to now and exp an hour later), and enter a secret or private key. The token is signed as you type; copy it, or click Verify in decoder to check it. This tool only makes signed tokens: it refuses alg: none, because servers must reject unsigned tokens anyway.

How do I sign a JWT with RS256?

Choose RS256 under Algorithm, then paste an RSA private key as a PKCS#8 PEM (BEGIN PRIVATE KEY) or a private JWK, or click Generate a key pair for a new 2048-bit key. The matching public key appears as PEM and JWK, with Copy as JWKS, for whoever verifies the token. An older BEGIN RSA PRIVATE KEY file must be converted first: openssl pkcs8 -topk8 -nocrypt -in key.pem -out pkcs8.pem. ES256 and the other key-pair algorithms work the same way.

Is it safe to paste a token or sign with a real secret here?

Decoding, verification and signing all run in your browser, and this tool doesn't send your token, secret or key anywhere. Ads don't load on this page; Vercel's cookie-free visit counter does. Still, a live token works like a password until it expires, and a real signing key can mint tokens your servers will trust. Prefer expired tokens and test keys, or generate a fresh key pair here; a key made here never leaves your browser.

Which algorithms can it verify and sign?

HS256, HS384 and HS512 with a shared secret (plain text or Base64), and RS256–512, PS256–512, ES256, ES384 and ES512 (curves P-256, P-384 and P-521) and EdDSA (Ed25519) with a key pair. To verify, the public key can be an SPKI PEM (BEGIN PUBLIC KEY), a JWK, or a JWKS, where the key whose kid matches the token is used. To sign, the private key can be a PKCS#8 PEM or a JWK. ES signatures use the raw r||s form JWS requires, not DER.

Decode vs verify vs validate

These are three different checks, and only a server that does all three should trust a token.

Supported algorithms

The alg header says how a token was signed (RFC 7518 for HS, RS, PS and ES; RFC 8037 for EdDSA).

algMethodSign with / verify withNotes
HS256, HS384, HS512HMAC with SHA-256/384/512The same shared secretRFC 7518 requires a key at least as long as the hash: 32, 48 or 64 bytes. See HMAC in the hash generator.
RS256, RS384, RS512RSASSA-PKCS1-v1_5RSA private key / public keyRFC 7518 requires RSA keys of 2048 bits or more; generated keys are 2048-bit.
PS256, PS384, PS512RSASSA-PSSRSA private key / public keySalt length equals the hash length (32, 48 or 64 bytes).
ES256ECDSA, SHA-256EC P-256 private key / public key64-byte raw r||s signature.
ES384ECDSA, SHA-384EC P-384 private key / public key96-byte raw r||s signature.
ES512ECDSA, SHA-512EC P-521 private key / public keyThe curve is P-521, not P-512. 132-byte raw r||s signature.
EdDSAEd25519Ed25519 (OKP) private key / public keyEd448 isn't supported. Needs a browser with Ed25519 in Web Crypto.
noneUnsignedNoneFlagged as unsigned when decoding, and refused when signing. Never accept these.

JWT claims reference

The first seven are the registered claims of RFC 7519; the others are common in OpenID Connect ID tokens and OAuth access tokens. Time claims are NumericDate values: whole seconds since 1970-01-01 UTC, not milliseconds.

ClaimNameMeaning
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 for. An API should reject tokens meant for another audience.
expExpiration timeAfter this time the token must be rejected.
nbfNot beforeBefore this time the token must be rejected.
iatIssued atWhen the token was created.
jtiJWT IDA unique ID, useful for revocation lists and replay checks.
azpAuthorized partyThe client the token was issued to (OpenID Connect).
scope, scpScopesWhat the token allows, as a space-separated string or a list.
nonceNonceTies an ID token to the login request that asked for it.
sid, auth_timeSession ID, authenticated atThe login session and when the user signed in.

Why signature verification fails

The tool reports these cases with a specific message:

JWT security pitfalls