JWT Encoder

Free online JWT encoder — build and sign a JSON Web Token with HS256 (HMAC-SHA256). Edit the header and payload, enter a secret, and get a signed JWT instantly. Uses the browser's native Web Crypto API — nothing you type here is ever sent to a server.

Algorithm

HS256 HMAC-SHA256

Symmetric signing — the same secret signs and verifies the token.

Load example

JWT structure

Header — alg, typ
Payload — claims, data
Signature — HMAC-SHA256

Runs in your browser

Signing happens locally via the Web Crypto API. Your secret, header, and payload are never sent to any server.

Never sent anywhere — the secret is used only in-browser via crypto.subtle to compute the HMAC signature.

Signed JWT

What is a JWT and why sign one?

A JWT (JSON Web Token) is an open standard (RFC 7519) for transmitting information as a compact, URL-safe JSON object. Signing a JWT proves it was issued by whoever holds the signing key and that its contents have not been altered in transit. This encoder builds that signature for you: it takes a header and payload you edit, base64url-encodes them, and signs the result with HMAC-SHA256 (HS256) using a secret you supply.

Signing a JWT is useful when you need to test an API that expects a bearer token, prototype an authentication flow, or simply understand how the three parts of a token fit together before wiring up a server-side library.

How HS256 signing works

HS256 stands for HMAC using SHA-256 — a symmetric algorithm where the same secret both signs and verifies the token. The process is three steps:

1. Encode

The header and payload JSON objects are each serialized with no extra whitespace, then base64url-encoded (standard base64 with +-, /_, and padding = removed) and joined with a dot: headerB64.payloadB64.

2. Sign

The joined string is passed through HMAC-SHA256 using your secret as the key. In the browser this is done with the native crypto.subtle API — no external library needed.

3. Append

The raw signature bytes are base64url-encoded and appended as the third segment, producing the final header.payload.signature token.

Change a single character in the header or payload and the signature changes completely — that's what makes a signed JWT tamper-evident.

How to sign a JWT with the Web Crypto API

This is the same approach this tool uses internally — no JWT library, just the browser's built-in cryptography:

function base64url(bytes) {
  let binary = '';
  bytes.forEach(b => binary += String.fromCharCode(b));
  return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

async function signJWT(header, payload, secret) {
  const enc = new TextEncoder();
  const headerB64  = base64url(enc.encode(JSON.stringify(header)));
  const payloadB64 = base64url(enc.encode(JSON.stringify(payload)));
  const signingInput = headerB64 + '.' + payloadB64;

  const key = await crypto.subtle.importKey(
    'raw', enc.encode(secret),
    { name: 'HMAC', hash: 'SHA-256' },
    false, ['sign']
  );
  const sigBuffer = await crypto.subtle.sign('HMAC', key, enc.encode(signingInput));
  const signature = base64url(new Uint8Array(sigBuffer));

  return signingInput + '.' + signature;
}

const token = await signJWT(
  { alg: 'HS256', typ: 'JWT' },
  { sub: '1234567890', name: 'John Doe', iat: 1516239022 },
  'your-256-bit-secret'
);

Already have a token and need to inspect it instead of creating one? Use our JWT decoder to decode the header, payload, and claims of an existing JWT.

Security notes

  • Don't treat this as a production secret generator. Use it to learn how JWT signing works or to build test tokens for local development — not to generate real credentials without understanding your own application's security requirements.
  • Use a strong, random secret. For HS256, the secret should be at least 256 bits (32 random bytes) of entropy. Short or guessable secrets can be brute-forced.
  • Never store sensitive data in the payload. The payload is only base64url-encoded, not encrypted — anyone with the token can read it.
  • Set an expiry (exp). Tokens without an expiration are valid indefinitely once issued.
  • Keep signing secrets server-side in production. If both the client and server hold the same HS256 secret, either side can forge tokens. For public clients, prefer an asymmetric algorithm like RS256 or ES256.

Frequently asked questions

A JWT encoder builds a JSON Web Token from a header and payload you supply, then signs it so the recipient can verify it has not been tampered with. This tool encodes the header and payload as base64url JSON, then signs the result with HMAC-SHA256 (HS256) using a secret you provide, producing a compact header.payload.signature token string.
This encoder runs entirely in your browser using the native Web Crypto SubtleCrypto API — your secret and payload are never sent to any server. That said, you should not use secrets or tokens generated here as real production credentials unless you understand your own application's security requirements. For production systems, generate secrets with a proper cryptographically secure random generator and manage them via a secrets manager.
HS256 (HMAC using SHA-256) is a symmetric JWT signing algorithm — the same secret key is used to both sign and verify the token. It works by computing an HMAC-SHA256 hash of the base64url-encoded header and payload, then appending that hash (also base64url-encoded) as the token's signature segment. Because the same secret verifies the token, HS256 is best suited to systems where the signer and verifier are the same trusted service or share the secret securely.
In the browser, use the Web Crypto API: base64url-encode the JSON header and payload, join them with a dot, import your secret with crypto.subtle.importKey('raw', ..., { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']), then sign the joined string with crypto.subtle.sign('HMAC', key, data). Base64url-encode the resulting signature bytes and append them as the third segment. In Node.js, the built-in crypto module's createHmac('sha256', secret).update(data).digest() does the same job synchronously.
A JWT encoder creates and signs a new token from a header, payload, and secret — the output is a token string. A JWT decoder does the reverse: it takes an existing token string and reveals its header and payload without needing any key (decoding does not require verification). Use an encoder when you need to build or test a token; use a decoder when you need to inspect one you already have. Try our JWT decoder for the reverse operation.
This tool is intended for learning, debugging, and quick local testing — for example generating a test token to call an API you're developing against. It is not a substitute for your production authentication system. Production tokens should be issued by your backend using a securely stored, sufficiently random secret (256 bits or more for HS256), with short expiry times and proper claim validation (iss, aud, exp).
The signature is a cryptographic hash of the exact header and payload bytes. Any change — even whitespace inside the JSON — changes the base64url-encoded input to the HMAC function, which changes the resulting signature. This is the security property that makes JWTs tamper-evident: a recipient who re-computes the signature and gets a different value knows the token was altered.