JWT Encoder — Create JWT Tokens Online
Create JSON Web Tokens instantly. Build JWT tokens with custom headers, payloads, and HMAC SHA256 signatures. Perfect for testing authentication flows, API integrations, and debugging token-based systems. Fully client-side — tokens and secrets are never sent anywhere.
What is a JWT? A JSON Web Token is three base64url-encoded segments joined by dots — header.payload.signature — defined by RFC 7519. The header names the signing algorithm, the payload carries the claims, and the signature is an HMAC or digital signature over the first two segments. Anyone can read a JWT; only a holder of the key can produce or verify a valid signature.
How to Use the JWT Encoder
-
Start from the sample, or write the header yourself — Sample Data fills all three fields with a realistic token — issuer, subject, audience, a one-hour expiry and a roles array — which is usually faster to edit than typing JSON from scratch. A minimal header is
{"alg":"HS256","typ":"JWT"}. -
Write the payload claims as JSON — Anything JSON-serialisable is allowed: strings, numbers, arrays and nested objects. The registered claims
exp,iatandnbfmust be numeric Unix seconds, not ISO date strings — the Timestamp Converter turns a date into the right integer. - Enter the HMAC secret — The secret is used as its raw UTF-8 bytes, exactly as typed — it is not base64-decoded first. If your backend stores the key base64-encoded, decode it before pasting or the signatures will never match. RFC 7518 asks for a key at least as long as the hash output, so 32 bytes or more for HS256.
-
Pick HS256, HS384 or HS512 — The radio buttons choose the HMAC hash. Whatever
algvalue you typed in the header is overwritten by this choice before signing, andtypis set toJWTif you left it out, so the header can never disagree with the signature. -
Click Encode JWT — Both JSON fields are parsed first; a syntax error stops the process and names the position. On success the three segments are assembled and shown in full, ready to paste after
Authorization: Bearer. - Copy the token, then clear the secret — Copy puts the token on the clipboard. Note that encoding also writes the header, payload and secret into the page URL so the state can be reloaded — clear the secret field before bookmarking or sharing that address.
How a Signed JWT Is Built
A JWT in the form this tool produces is a JWS Compact Serialization, described in RFC 7515. Building one is three deterministic steps, and knowing them makes almost every "invalid signature" bug obvious.
token = base64url(header) + "." + base64url(payload) + "." + base64url(HMAC(key, header64 + "." + payload64))
First the header and the payload are serialised to compact JSON and encoded with base64url —
the standard base64 alphabet with + replaced by -, / by _,
and the trailing = padding removed, so the result is safe in a URL or an HTTP header. Then those
two segments are joined with a dot to form the signing input. Finally that exact string of ASCII characters —
not the original JSON — is signed with HMAC using your secret, and the resulting bytes are base64url-encoded
as the third segment.
Because the signature covers the encoded text rather than the parsed objects, byte-for-byte reproduction matters. Re-serialising the same claims with different key ordering, different spacing or a different Unicode escaping strategy produces a different signing input and therefore a different signature — which is why a verifier must never re-encode a token it received, and why comparing two tokens built from "the same" JSON in two languages can be misleading.
The HMAC itself is computed by the browser's Web Crypto API through crypto.subtle.importKey and
crypto.subtle.sign — the same native implementation the browser uses for TLS, not JavaScript
arithmetic. Web Crypto is only available in a secure context, so the page needs HTTPS or
localhost.
Supported Algorithms
| Header value | Algorithm | Signature length | Notes |
|---|---|---|---|
HS256 | HMAC with SHA-256 | 32 bytes (43 base64url chars) | The default and by far the most widely deployed |
HS384 | HMAC with SHA-384 | 48 bytes (64 chars) | Larger margin; supported by most libraries |
HS512 | HMAC with SHA-512 | 64 bytes (86 chars) | Longest tag; the token grows accordingly |
All three are symmetric: the same secret both creates and verifies the signature, so every party that can
check a token can also mint one. That is fine inside a single service and wrong across a trust boundary —
when a third party must verify but not issue, you need an asymmetric algorithm such as RS256 or
ES256, where a private key signs and a public key verifies. Those require a key pair and are not
offered here; generate them with your platform's crypto library instead.
Registered Claims
RFC 7519 reserves a short list of claim names with agreed meanings. None of them is mandatory, but libraries validate these automatically when present, so using them is what makes a token portable between stacks. All time values are Unix seconds — integers, not milliseconds and not date strings.
| Claim | Name | Meaning | Example |
|---|---|---|---|
iss | Issuer | Who minted the token; verifiers usually pin this | "https://auth.example.com" |
sub | Subject | The principal the token is about, typically a stable user id | "user_1234567890" |
aud | Audience | Who the token is for; an API should reject tokens minted for another audience | "api.example.com" |
exp | Expiration | Unix seconds after which the token must be rejected | 1735689600 |
nbf | Not Before | Unix seconds before which the token is not yet valid | 1735603200 |
iat | Issued At | When the token was created; used for age limits | 1735603200 |
jti | JWT ID | A unique id, so a single token can be denylisted or replay-checked | "jwt_9f2b1c7a" |
Everything else is a custom claim and is simply passed through: roles, scope,
tenant, org_id and so on. The convention for private claims is to namespace them
with a URI you control so two systems merging tokens cannot collide on a bare name.
Security Notes
Treat every token you build here as disposable test data. Encoding writes the header, payload and secret into this page's URL so the state can be restored, which means a real signing key would land in your browser history and in anything you paste the link into. Use a throwaway secret, and mint production tokens on a server where the key lives in an environment variable or a vault.
- A JWT is signed, not encrypted. The payload is base64url text that anyone holding the token can read in a second. Keep passwords, card numbers and anything else confidential out of it; if the contents must be hidden, you need JWE rather than JWS.
- Always set
exp. A token with no expiry is valid until the signing key changes. Short lifetimes plus a refresh mechanism beat long-lived tokens, because a plain JWT cannot be revoked once issued — a verifier only checks the signature and the claims. - Pin the algorithm on the verifying side. Historic attacks worked by editing the header: setting
algtononeso no signature is required, or switching anRS256token toHS256so the public key gets used as an HMAC secret. Configure your library with the exact algorithm you expect instead of trusting the header. - Size the secret properly. A short, guessable HMAC key can be brute-forced offline from a single captured token. Use at least 32 random bytes for HS256 and treat it like a password, not a label.
- Send tokens only over TLS, and prefer the
Authorizationheader over a query string so the token does not end up in server logs, proxy logs or aRefererheader.
Frequently Asked Questions
A compact, URL-safe way to carry signed claims between parties, standardised as RFC 7519. It is three base64url segments separated by dots: a header naming the algorithm, a payload of JSON claims, and a signature over the first two. Because the signature covers the encoded segments, any change to the header or payload invalidates it — that is what lets a receiver trust the contents without calling back to the issuer.
HS256, HS384 and HS512 — HMAC with SHA-256, SHA-384 and SHA-512, as defined in RFC 7518. Asymmetric algorithms such as RS256, PS256 and ES256 are not offered because they need a generated key pair rather than a shared string. Whatever alg you type in the header is replaced by the radio selection before signing, so you cannot produce an alg: none token here.
It is never transmitted: the signature is computed locally by the browser's Web Crypto API. It is, however, written into the page URL together with the header and payload after a successful encode, so it appears in your address bar and browser history. Use a disposable secret, and clear the field before copying or sharing the link.
Only as test fixtures. Real tokens should be minted by your backend, where the signing key is held in an environment variable or a secrets manager, rotated on a schedule and never exposed to a browser. What this tool is genuinely good for is producing a token with exactly the claims you want so you can exercise an endpoint, a middleware or a role check.
Four causes account for almost all of them. The secret is being treated as base64 on one side and as literal text on the other — this tool signs with the raw UTF-8 bytes of what you type. The algorithms differ, because the header was rewritten to match the radio button. The token expired, since exp is compared against the verifier's clock. Or a whitespace character was copied along with the token.
Add exp to the payload as an integer number of seconds since 1 January 1970 UTC — for example 1735689600. Milliseconds are a common mistake and produce a token dated tens of thousands of years in the future, which most libraries accept silently. Convert a real date with the Timestamp Converter, and use JWT Decoder to read back what the token actually says.
No. Base64url is an encoding, not encryption, and the payload of any JWT can be read by pasting it into a decoder. Put an identifier in the token and keep the sensitive record on the server. If the claims themselves must be confidential in transit and at rest, the JWT family answer is JWE, a different specification from the signed tokens produced here.
A session cookie is a pointer: the server keeps the state and can drop it instantly, so logout and revocation are immediate. A JWT carries the state itself, so a verifier needs no shared database — which is what makes it useful across services — but it stays valid until it expires, because nothing consults a central store. Teams often run both: short-lived JWTs for API calls plus a revocable refresh token.
Use Cases
Testing Auth Endpoints
Generate JWT tokens with specific claims to test protected API routes and verify access control logic.
Debugging Token Formats
Create tokens with specific header or payload structures to debug serialization issues in your auth library.
Prototyping Auth Flows
Quickly build JWT tokens with custom claims to prototype authentication workflows before implementing backend logic.
Security Auditing
Generate tokens with intentionally invalid or malformed claims to test how your system handles edge cases.