JWT Encoder
Sign a JSON payload with an HMAC secret to produce a valid JSON Web Token. Everything runs locally in your browser via the Web Crypto API — your secret never leaves the page.
Encoding…
Verify the result with the JWT Decoder or check your secret's strength in the Validator.
How to sign a JWT in 4 steps
- 1. Edit the Payload box with your claims:
sub,iat,exp, plus anything app-specific. - 2. Pick an algorithm — HS256 for most APIs; HS512 for long-lived or high-value tokens.
- 3. Paste a secret generated by the Secret Generator (at least 32 bytes).
- 4. Copy the signed token on the right and verify it in the Decoder.
Server-side signing examples
import jwt from "jsonwebtoken";
const token = jwt.sign(
{ sub: "user_123", role: "admin" },
process.env.JWT_SECRET,
{ algorithm: "HS256", expiresIn: "15m" }
);import jwt, os, time
token = jwt.encode(
{"sub": "user_123", "exp": int(time.time()) + 900},
os.environ["JWT_SECRET"],
algorithm="HS256",
)import (
"time"
"github.com/golang-jwt/jwt/v5"
)
claims := jwt.MapClaims{
"sub": "user_123",
"exp": time.Now().Add(15 * time.Minute).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signed, _ := token.SignedString([]byte(os.Getenv("JWT_SECRET")))curl https://api.example.com/me \ -H "Authorization: Bearer $TOKEN"
Related tools
Before signing anything real, generate a properly random key with the JWT secret generator — see all available formats and lengths on the generator variants page. After signing a token here, confirm it round-trips correctly in the JWT decoder, and double-check the secret itself meets HS256/384/512 entropy requirements with the JWT secret validator. If you're still fuzzy on why JWTs have three segments in the first place, read What is a JWT?. We walk through common signing bugs and framework-specific gotchas on the blog, and answer shorter questions on the FAQ page. Once your token is signed, the fastest way to sanity-check the claims is pasting it into the decoder side by side with this page.
What is a JWT encoder?
A JWT encoder (often called a JWT signer) is the operation that turns a plain JSON payload into a tamper-evident JSON Web Token. It is the mirror image of decoding: instead of reading claims out of an existing token, you write claims in, choose a signing algorithm, and supply a key. The encoder serializes the header and payload to JSON, Base64URL-encodes each one, joins them with a dot, and computes a Message Authentication Code (for HMAC algorithms like HS256) or a digital signature (for RSA/ECDSA algorithms) over that joined string. The result — three dot-separated segments — is what your application sends as a Bearer token or session credential. Encoding is useful for testing an API that expects a JWT, prototyping auth flows before your backend is wired up, or understanding exactly what your server-side library is doing under the hood.
How JWT signing works, step by step
- 1. Build the header.
{"alg":"HS256","typ":"JWT"}— this tool sets it automatically based on the algorithm you pick. - 2. Base64URL-encode header and payload. Each JSON object is UTF-8 encoded to bytes, then Base64URL-encoded (no padding, URL-safe alphabet).
- 3. Concatenate with a dot. This produces the "signing input":
base64url(header) + "." + base64url(payload). - 4. Sign the signing input. For HS256/384/512, the browser's Web Crypto API imports your secret as a raw HMAC key and runs
crypto.subtle.sign("HMAC", key, data)with SHA-256/384/512 as the underlying hash. - 5. Append the signature. The signature bytes are Base64URL-encoded and appended with another dot, giving the final
header.payload.signaturestring.
Worked example
With the default payload {"sub":"1234567890","name":"Jane Doe","iat":1700000000,"exp":1700003600} and secret your-256-bit-secret on HS256, the encoder first builds the signing input eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDAwMDM2MDB9. It then computes HMAC-SHA256 of that string using the secret as the key, Base64URL-encodes the 32-byte digest, and appends it as the third segment — producing a full token you can paste straight into the decoder to confirm the header and payload round-trip exactly. Change the secret by a single character and re-sign: the header and payload segments stay identical, but the signature segment is completely different, which is exactly what a verifier checks for.
Common mistakes when signing JWTs
- Using a short, human-memorable secret (like a word or short phrase) — HS256 needs a full 256 bits (32 random bytes) of entropy, not a password.
- Forgetting to set
exp, producing a token that never expires and becomes a permanent credential if leaked. - Signing on the client and shipping the secret to the browser in a real application — this demo runs client-side for learning purposes only; production secrets must stay server-side.
- Mismatching algorithms between signer and verifier (e.g. signing with HS512 but verifying with HS256), which always fails even with the correct secret.
- Embedding large or sensitive objects in the payload — JWTs are sent on every request, so bloated payloads waste bandwidth and every claim is readable by anyone holding the token.
Security notes
Treat your signing secret like a password to your entire authentication system — anyone who has it can mint valid tokens for any user. Generate secrets with a cryptographically secure random source (never Math.random()), store them in a secrets manager or environment variable rather than in source control, and rotate them on a schedule or immediately after any suspected leak. In real applications, signing must happen on a trusted server — this in-browser encoder exists so you can learn the mechanics and test payloads, not to sign production tokens from client-side JavaScript. Also remember that JWTs are integrity-protected, not confidential: never put a value in the payload that the token holder shouldn't be able to read.
JWT Encoder FAQ
What does a JWT encoder do?
It takes a JSON payload, adds a header describing the algorithm, and signs the two together with your secret using HMAC (HS256/HS384/HS512). The result is a compact, URL-safe JWT you can send in an Authorization header.
Is my secret sent to a server?
No. Encoding and HMAC signing happen entirely in your browser through the Web Crypto API (crypto.subtle.sign). Nothing is transmitted, logged, or stored.
Which algorithm should I pick?
HS256 is the default and fine for most APIs. Use HS384 or HS512 only when you need matching-strength secrets and are prepared to store 48- or 64-byte keys.
Can I use RS256 or ES256 here?
This encoder covers HMAC (symmetric) algorithms. RS256/ES256 require an RSA or ECDSA private key and are typically signed on a trusted server, not in the browser.
Why does changing one character in the payload completely change the signature?
HMAC treats header+payload as a single byte string input to a cryptographic hash function. Hash functions exhibit the avalanche effect — flipping even one bit of input produces a completely different, unpredictable output. That's what makes tampering detectable.
Do I need to include 'iat' and 'exp' myself?
Yes, this encoder signs exactly the JSON you provide. Production libraries like jsonwebtoken often add iat automatically and compute exp from an expiresIn option, but a raw encoder like this one won't add anything you didn't type.
What happens if my payload JSON is invalid?
The encoder shows a parsing error instead of a token. JWT payloads must be a valid JSON object (or at minimum valid JSON) — trailing commas, unquoted keys, or single quotes will all fail to parse.
Can two different secrets ever produce the same signature for the same payload?
In theory yes (a hash collision), but for HMAC-SHA256/384/512 this is computationally infeasible with current technology — that's exactly the property that makes HMAC signatures trustworthy for authentication.
Related tools
Recent articles
Guides on JWT secrets, signing algorithms, and token security.