Edit the JWT header and payload as raw JSON with live validation. Pre-populated with standard claims (`iss`, `sub`, `aud`, `exp`, `iat`, `nbf`, `jti`) so you don't have to remember which is which. Errors highlighted as you type.
Free JWT encoder / generator — sign JSON Web Tokens with HS256, HS384, HS512, RS256, ES256, and EdDSA in the browser.
JWT Encoder builds and signs a JSON Web Token from your header and payload, entirely in your browser — no server round-trip, no secret leaves your machine. Supports every standard signing algorithm: HMAC (HS256 / HS384 / HS512), RSA (RS256 / RS384 / RS512), RSA-PSS (PS256 / PS384 / PS512), ECDSA (ES256 / ES384 / ES512), and EdDSA (Ed25519). Lets you author header / payload as JSON, paste or generate a key, pick an algorithm, and produce a real signed token ready to use.
What this tool does
Six independent classes of functionality. Header / payload authoring and signing are the obvious headlines; the in-browser cryptography (no key ever sent to a server), the algorithm flexibility, and the standard-claim helpers are the differentiators.
HS256 / HS384 / HS512 (HMAC with shared secret), RS256 / RS384 / RS512 (RSA), PS256 / PS384 / PS512 (RSA-PSS), ES256 / ES384 / ES512 (ECDSA), EdDSA (Ed25519). The tool sets the `alg` claim in the header automatically; never let the wrong one slip through.
For HMAC: paste any string as the secret. For asymmetric: paste a PEM-encoded private key, generate a fresh key pair in-browser, or upload a key file. Asymmetric public key is also surfaced so you can share it for verification.
Signing happens entirely client-side using the browser's Web Crypto API. Your secret or private key never leaves your device. No server round-trip, no logging, no risk of secret leakage.
Buttons to insert standard time-bound claims with sensible defaults. `iat` (issued-at) gets the current Unix time. `exp` (expires) defaults to 1 hour from now (configurable). `nbf` (not-before) defaults to now. `jti` (JWT ID) auto-generates a UUID.
Once signed, copy the compact JWT (`header.payload.signature`) to clipboard, generate a ready-to-use `curl` command with `Authorization: Bearer ...`, or get a JS snippet that calls a fetch with the token attached.
Why an in-browser JWT signer beats a server one
Most online JWT tools send your secret to their server to do the signing. That's almost always a mistake. Four reasons in-browser signing matters:
- Your signing key is the keys-to-the-kingdom credential A JWT signing key (HMAC secret or RSA private key) lets the holder mint arbitrary tokens. Anyone who has it can impersonate any user, escalate to admin, bypass authentication entirely. Pasting it into a server-side JWT tool is functionally the same as posting it in a public Slack channel.
- In-browser signing keeps the key local The Web Crypto API does all the signing client-side. The key never touches the network. The tool's server never sees it; the tool's developer never sees it. Even if our entire backend were compromised, your signing key would be unaffected.
- Useful during development without exposing prod secrets Need a token to test a protected endpoint? Generate one with your local dev secret right here. Done. No need to fish around for the right script or expose the secret to a third-party tool. Production secrets stay where they belong; dev tokens are immediate.
- Lets you verify your library is doing the right thing Comparing the token your auth library produces against the token this tool produces (given the same input and key) is a quick way to validate library behavior. If they differ, one is wrong.
Author JSON, encode, sign, concatenate
JWT signing is mechanical. Three pieces (header, payload, signature) base64url-encoded and concatenated with dots. The signing happens over the encoded `header.payload` string, not the raw JSON.
- Stage 1 — Author header + payload Write the header as JSON. Required field: `alg` (which the tool sets automatically based on your algorithm choice). Standard: `typ: 'JWT'`. Write the payload as JSON with whatever claims your application uses — standard claims (`iss`, `sub`, `aud`, `exp`, etc) plus any custom ones.
- Stage 2 — Base64url-encode each part Header and payload each get JSON-stringified, UTF-8 encoded, then base64url-encoded (note: URL-safe variant, no padding). This is the wire format defined by RFC 7519.
- Stage 3 — Build the signing input Concatenate `<encoded-header>.<encoded-payload>` into a single ASCII string. This is what gets signed — not the raw JSON, not the decoded bytes.
- Stage 4 — Sign with your key For HMAC algorithms (HS256/384/512), compute HMAC of the signing input using the shared secret. For RSA / ECDSA / EdDSA, sign the signing input with the private key. The Web Crypto API handles all of this client-side.
- Stage 5 — Base64url-encode the signature The signature bytes get base64url-encoded (same URL-safe, padding-stripped variant). Concatenate as the third dot-separated segment.
- Stage 6 — Output the compact JWT Final token: `<encoded-header>.<encoded-payload>.<encoded-signature>`. Copyable as a single string. Ready to drop into an `Authorization: Bearer ...` header.
When to pick which signing algorithm
The `alg` choice determines whether your tokens are HMAC-shared-secret or asymmetric-key signed — a foundational architectural decision. Five categories:
- HMAC (HS256 / HS384 / HS512) Symmetric — same secret signs and verifies. Fast, simple. Appropriate when one entity both issues and verifies tokens (a single API authenticating its own users). NOT appropriate when verifiers shouldn't be able to mint tokens — anyone with the verify key can sign. HS256 is the most common; HS512 just uses a larger hash.
- RSA (RS256 / RS384 / RS512) Asymmetric — private key signs, public key verifies. The verifier can't forge. Standard for OAuth / OpenID Connect — the IdP signs with private key, every resource server verifies with the public key (often published via a JWKS endpoint). Key sizes: 2048-bit minimum; 3072 or 4096 for higher assurance. Larger keys mean slower verification but it's still fast.
- RSA-PSS (PS256 / PS384 / PS512) Asymmetric — like RS256 but with the Probabilistic Signature Scheme padding. Slightly more secure padding (PKCS#1 v1.5 used by RS256 is considered legacy but still safe). Same key sizes. Use when you're starting fresh and have library support; RS256 is still acceptable for compatibility.
- ECDSA (ES256 / ES384 / ES512) Asymmetric — Elliptic Curve Digital Signature Algorithm. Much smaller keys and signatures than RSA at equivalent security (256-bit ECDSA ≈ 3072-bit RSA). Faster than RSA. Standard choice for new asymmetric deployments where small token size matters (cookies, headers, mobile).
- EdDSA (Ed25519) Asymmetric — modern, deterministic, fast. 256-bit keys. Resistant to several attack classes that affect ECDSA. Best choice for new asymmetric deployments when you control both ends and library support is confirmed. Less universally supported than RS256/ES256.
- Never use `alg: none` JWT spec allows `alg: none` (unsigned token). Several historic attacks worked by changing the alg field to 'none' on a token that was supposed to be signed. Always reject 'none' on the verify side. The tool does not offer 'none' as a signing option.
Things that go wrong with JWTs
JWTs are easy to use poorly. Five common pitfalls to avoid:
- Long expiration times JWTs are stateless — once issued, they're valid until `exp`. There's no revocation list by default. A `exp` of 30 days means a stolen token works for 30 days. Best practice: short-lived access tokens (5-15 minutes) plus refresh tokens (longer-lived, but revocable on the server).
- Missing or sloppy verification A common XSS exfiltration → JWT replay attack works because the receiving service didn't verify the signature properly (or used a library with an alg-confusion vulnerability). Always verify with the exact expected algorithm; never let the token's own `alg` header drive verification.
- Sensitive data in the payload JWT payloads are NOT encrypted — only signed. Anyone with the token can base64url-decode the payload and see everything. Don't put passwords, PII, secret tokens, or anything you wouldn't put in a log line. If you need confidentiality, use JWE (JSON Web Encryption), not JWS (JSON Web Signature).
- Algorithm confusion attacks Historic vulnerability class: a service expecting RS256 (asymmetric, verifying with public key) gets sent a token signed with HS256 (symmetric, using the public key as the HMAC secret). The forged token passes because the lib trusted the alg header. Modern libs guard against this — but only if configured correctly.
- Lack of key rotation JWT signing keys should rotate. JWKS (JSON Web Key Set) endpoints make rotation graceful — publish multiple keys with `kid` (key ID) header, retire old keys after their tokens expire. Without rotation, a key compromise is catastrophic; with rotation, it's recoverable.
How developers use a JWT encoder
Six patterns we see most often:
Need to test a protected endpoint locally. Generate a JWT with your dev secret, paste into curl or Postman. Faster than running the full auth flow. Don't use this approach with production secrets.
Compare your library's output against this tool's. Same header, same payload, same key, same algorithm should yield the same token byte-for-byte. If they don't, one is wrong (usually the library's serialization order or padding handling).
Build tokens with edge-case claims — empty arrays, unicode, very long strings, future-dated `nbf` — to test how your verifier handles them. Easier than mocking the issuer.
Some APIs (GitHub Apps, Snowflake key-pair auth, Apple Sign In) accept JWTs signed by your registered key as authentication. Generate a token with the right claims and you can call the API. Useful for one-off scripts.
Show what's actually inside a JWT to someone learning OAuth or OIDC. Demonstrate signature verification by changing one byte and watching it fail. Visual learning beats reading the spec.
Use the JWT Decoder to see what's in an existing token; build a similar one with this tool to test what happens when a specific claim changes. Helpful when debugging authorization bugs.
Common questions
- What is a JWT? JSON Web Token — a compact, URL-safe token format defined by RFC 7519. Consists of three base64url-encoded parts (header, payload, signature) joined by dots. The signature lets the receiver verify the token was issued by someone with the signing key and hasn't been tampered with. Used pervasively in OAuth 2.0, OpenID Connect, and modern API authentication.
- Is my secret safe with this tool? Yes — the signing happens entirely in your browser via the Web Crypto API. Your secret or private key never leaves your machine. We don't have it; we couldn't get it even if we wanted to. The tool's server doesn't even know what algorithm you picked, let alone the key.
- Which JWT algorithm should I use? For a single service that both issues and verifies its own tokens: HS256 (HMAC-SHA256) is simple and fast. For OAuth / OIDC where many services verify tokens issued by one IdP: RS256 (RSA-2048) is standard, ES256 (ECDSA-P256) is the modern slightly-better choice, EdDSA (Ed25519) is the most modern but requires library support on every verifier. Never use `alg: none`.
- Why is my JWT being rejected? Common causes: (1) algorithm mismatch — the issuer signed with HS256 but the verifier expects RS256, (2) signature key mismatch — verifier is using a different key than the issuer signed with, (3) token expired — `exp` claim is in the past, (4) `nbf` (not-before) in the future, (5) audience mismatch — `aud` claim doesn't match the verifier's expected value, (6) issuer mismatch — `iss` claim doesn't match expected. Use the JWT Decoder to inspect what's actually in the token.
- What's the difference between JWT signing and JWT encryption? Signing (JWS — what this tool does) makes the token tamper-evident. The payload is visible to anyone with the token — base64url is not encryption. Encryption (JWE) wraps the payload in an encrypted envelope so only holders of the decryption key can read it. JWE is rarely needed in OAuth flows; signing is the default. If you have sensitive data, either don't put it in the JWT or use JWE.
- How long should my JWT expiration (`exp`) be? Access tokens: 5-15 minutes is typical. Short enough that a stolen token has limited utility; long enough that you don't refresh on every request. Refresh tokens: hours to days, depending on application. Refresh tokens should be revocable server-side (a JWT is not naturally revocable, so a refresh token is usually a database-backed opaque value, not a JWT).
- What's the difference between this and the JWT Decoder? This tool builds and signs new JWTs. The JWT Decoder takes an existing JWT and parses it — showing the header, payload, and signature plus optionally verifying the signature if you provide the key. The two are paired: encoder for creation, decoder for inspection.
- Can I use this for production token generation? Functionally yes — the signing is correct and the output is a real JWT. Operationally no — production token issuance should happen on your authentication service, not in a developer's browser. This tool is for development, debugging, testing, and learning. Use a real auth library (e.g., `jose` for Node, `PyJWT` for Python, `golang-jwt/jwt` for Go) for production.