JWT Encoder
Build a token from claims, and really sign it · runs in this tab, never sent anywhere
Header
Payload
Signing key
The key is used and dropped — never saved in this browser, never sent anywhere.
A signing key mints tokens your systems will accept. For a production key, prefer your own environment.
HS256
Signed token
The signed token appears here. Nothing is uploaded to produce it — the signature is computed by this browser.
How the JWT Encoder works
A JWT encoder that produces a genuinely signed token rather than a base64 lookalike. Write the header and payload as JSON, pick an algorithm, and paste the shared secret for an HS algorithm or a PKCS#8 private key for RS, PS or ES — the signature is computed by your browser’s own WebCrypto. Expiry, issued-at and not-before can be stamped from presets so you never hand-convert an epoch again, and the finished token is checked against the decoder before it is shown.
Write the header and the payload as JSON, choose an algorithm, and the token is assembled and signed as you type. The expiry presets stamp iat, exp and optionally nbf into the payload from a single instant, so the three can never disagree by a second — which is the sort of thing that only fails inside someone else's clock-skew tolerance.
alg is always written from the algorithm you chose, whatever your header says. That is not a convenience: a header claiming one algorithm over a signature made with another is the setup for the best-known JWT vulnerability, and there is no legitimate token this tool would refuse to make as a result. Every other header field you write is kept exactly as you typed it.
HS secrets shorter than the hash are rejected by default — RFC 7518 requires 32 bytes for HS256, 48 for HS384 and 64 for HS512, and a browser will sign with four characters quite happily even though the result can be cracked offline in seconds. The check can be switched off, because reproducing a weak token is sometimes the whole point.
The signing key is treated the way the decoder treats its verification key, and more carefully still: it is never written to localStorage, never restored on refresh, never in an analytics event, and there is no backend that could receive it. A signing key is the most dangerous secret in a system that uses JWTs, so for a production key, minting tokens in your own environment remains the better habit.
Common questions
Is it safe to paste a signing key into this encoder?
The key is used in your own tab and dropped — never written to storage, never included in an analytics event, and there is no backend that could receive it. That said, a signing key is the most dangerous secret in any system that uses JWTs, because whoever holds it can mint tokens your services will accept. For a production key, generating tokens in your own environment is still the better habit; this tool is built for development, testing and learning.
Which algorithms can it sign with?
HS256, HS384 and HS512 with a shared secret, and RS256/384/512, PS256/384/512 and ES256/384/512 with a private key given as a PKCS#8 PEM block or a private JWK. It will also produce the unsecured `alg: none` token, clearly marked as proving nothing, because reproducing one is how you test that your verifier rejects it.
Why does it refuse my short secret?
RFC 7518 requires an HMAC key at least as long as the hash — 32 bytes for HS256, 48 for HS384, 64 for HS512. Browsers will happily sign with a four-character secret, and the resulting token can be cracked offline in seconds. The encoder blocks that by default and lets you override it, since reproducing a weak token is sometimes exactly the task.
Can it overwrite the algorithm in my header?
It always writes `alg` from the algorithm you picked, and that is deliberate. A header claiming one algorithm over a signature made with another is not a token, it is the setup for the best-known JWT vulnerability. Every other header field you write — `kid`, `cty`, anything custom — is kept exactly as you typed it.
How do I set the expiry?
Press one of the expiry presets and `iat`, `exp` and optionally `nbf` are stamped into the payload as NumericDate seconds, all from the same instant so they cannot disagree by a second. You can also type the numbers yourself; the encoder does not require the presets.