An HS256 JSON Web Token is a compact, three-segment string formed by base64url-encoding a fixed header {"alg":"HS256","typ":"JWT"}, base64url-encoding a strict JSON claims payload, and appending a third segment that holds the base64url-encoded HMAC-SHA-256 of the byte sequence header.payload using a shared secret. The compact form is defined in RFC 7515, the HMAC-SHA-256 algorithm and its minimum key size are defined in RFC 7518, and the entire signature is computed in the browser through Web Crypto, so the secret and the claims never leave the current tab. Because HS256 is a message authentication code rather than an encryption scheme, anyone who receives the token can decode the header and the payload without the secret. The signature is what lets the verifier detect modification after the fact, and the secret is what binds that detection to the issuing party. The result is a portable string shaped like xxxxx.yyyyy.zzzzz that any conforming JOSE library on any platform can verify, provided it knows the same secret, the same algorithm, and the same claim policy.

generate jwt token with secret key online
Generate a JWT Token With a Secret Key Online (HS256)

The secret key rules: 32 UTF-8 bytes and why

For HS256, the secret is the entire trust anchor. The HMAC-SHA-256 algorithm uses a 256-bit internal state, so the secret is expected to land at or above the 32-byte / 256-bit floor stated in RFC 7518. Anything shorter weakens the keyspace against brute-force attacks, so the JWT Generator rejects secrets below 32 UTF-8 bytes before signing begins.

Because the secret is hashed as a byte sequence, character count and byte count can diverge. A 32-character ASCII string is exactly 32 bytes. A 32-character string containing any non-ASCII character, whether emoji, accented Latin, or CJK glyphs, will exceed 32 bytes because UTF-8 encodes those code points across two, three, or four bytes. The tool treats your secret as raw UTF-8, then hands those bytes to Web Crypto as an HMAC key.

The random button on the generator is built for test fixtures. It draws 32 cryptographically random bytes from the browser's secure random source and displays them as 64 hexadecimal characters. Those 64 characters are then re-encoded as UTF-8 and used as the HMAC secret, yielding 32 bytes of cryptographic entropy rendered as a 64-character hex string. Treat the displayed string as visible test material: any browser tab, screenshot, clipboard, or chat log that captures it has captured the secret.

For any environment beyond local development, the secret belongs in a managed store such as a vault or a cloud secrets manager, not in a config file or a chat message. The generator's role is to help you sign a development token without forcing you to write a script, not to provision production credentials.

Generate the HS256 token with the JWT Generator

  1. Open the JWT Generator in your browser. The page renders two input panes and a token preview area; nothing executes until you click generate.
  2. Paste a strict JSON object into the claims pane. The object must begin with { and end with }, and it must not contain comments, trailing commas, NaN, Infinity, undefined, or JavaScript expressions. Arrays and null are rejected at the parser level.
  3. Enter your non-production secret into the secret field, or click the random button to fill it with 64 hexadecimal characters backed by 32 cryptographically random bytes.
  4. Confirm the secret is at least 32 UTF-8 bytes. The page surfaces a length hint so you can tell when non-ASCII text pushed the byte count above the character count.
  5. Click generate. The page base64url-encodes the fixed header and your claims, signs header.payload with HMAC-SHA-256 over the secret bytes, and emits the third signature segment without padding.
  6. Review the three segments on screen. The header should read {"alg":"HS256","typ":"JWT"} once decoded; the payload should match your input byte-for-byte; the signature should be the only segment that changes when you edit the secret.
  7. Copy the full xxxxx.yyyyy.zzzzz string. Treat the clipboard as a leak surface: clear it after pasting the token into your test environment, and never reuse the secret elsewhere.

Read the three compact segments

The compact form has three segments separated by periods. Each segment is a base64url string with no equals padding, which is why the segments contain only the characters [A-Za-z0-9_-] and never end with =.

SegmentSourceEncodingWhat it carries
Header{"alg":"HS256","typ":"JWT"}UTF-8 → base64url, no paddingAlgorithm and type identifier
PayloadYour strict JSON claims objectUTF-8 → base64url, no paddingIssuer, audience, subject, expiry, and any custom data
SignatureHMAC-SHA-256(header + "." + payload, secret bytes)base64url, no paddingIntegrity proof tied to the secret

The JWT Generator fixes the header at alg HS256, typ JWT. Fixing the algorithm prevents the kind of silent downgrade where a user pastes alg: none or alg: RS256 into the header and the recipient blindly accepts whatever shape arrives. Other algorithms require different key types, and the browser-based secret flow only models symmetric HMAC keys, so the page locks the choice.

The payload segment is exactly your JSON object, with no normalization beyond compact serialization. JSON.parse on the verifier side should reproduce the same object you pasted, including key order, because the page emits the compact form that the same JSON.stringify step would produce in JavaScript. If you need a stable byte sequence for deterministic verification, paste a claims object that already sorts in the order you want and avoid adding comments or trailing commas.

The signature segment is recomputed on every generation, so changing any input, even a single byte in the secret, produces a completely different third segment. This is the property that lets a verifier detect modification, provided the verifier uses the same secret and the same algorithm.

Verify the token with your target JOSE library

The JWT Generator emits a syntactically valid HS256 token, but it does not run a verification round-trip on its own output. Before you trust the token in any environment, hand it to the JOSE library your application actually uses and ask for an explicit, policy-driven check.

  1. Pass the copied string to the library's verify or decode function with the exact algorithm pinned to HS256. Reject any token whose protected header carries a different alg.
  2. Pass the same secret you used in the generator as the verification key. The secret bytes must match exactly, including encoding, padding, and trailing characters.
  3. Validate the iss claim against your expected issuer identifier. A token issued for one tenant should not be accepted by another.
  4. Validate the aud claim against the audience your service expects. A token minted for a different API is not yours to accept.
  5. Validate exp, nbf, and any leeway you have configured for clock skew. Reject expired tokens and not-yet-valid tokens.
  6. Validate jti if your service uses replay protection, and look up a revocation list if your service supports revocation.

Production libraries give you those checks in one call with explicit options. The verification pass is where most algorithm-confusion and key-confusion attacks are caught, so never skip it, even for tokens you produced yourself.

For a closer look at the algorithm comparison that frames HS256 against RS256 in the same browser workflow, the HS256 vs RS256 guide walks through the trade-offs you weigh before picking a symmetric secret flow.

What the JWT Generator does not do

The page is scoped to producing a development token. It does not add iat, exp, nbf, iss, sub, aud, jti, or any other claim automatically. If your verifier expects a NumericDate exp claim, you must place that integer inside your claims object, expressed in seconds since the Unix epoch, not in JavaScript milliseconds.

For example, the moment 2026-01-01T00:00:00Z corresponds to NumericDate value 1767225600, because the Unix epoch second for the start of 2026 in UTC is 1767225600 seconds. If you paste milliseconds by mistake, the verifier will interpret your expiry as billions of years away or far in the past, even though the human-readable date looked correct.

The page also does not verify the token it just created, contact an identity provider, publish a JWK, store a key, select a kid, encrypt claims, or produce RS256, ES256, EdDSA, JWE, or unsecured tokens. It does not auto-rotate the secret, audit usage, or revoke a leaked token. None of those concerns belong in a browser page that processes key material in memory; they belong in a maintained JOSE library and your application's trust policy.

Finally, the page does not advertise uniqueness. Other browser-based JWT tools exist, and several let you pick a different algorithm or accept an unsecured header. The deliberate scope of this generator is HS256 with a minimum 32-byte UTF-8 secret, because that is the safest shape for a development flow without adding options that quietly weaken verification.

Common mistakes with secret-key JWTs

A short secret is the most common failure. Anything below 32 UTF-8 bytes is rejected, but pasting a single dictionary word with punctuation will still pass the character test in your head and fail the byte test at signing time. If your verifier complains about a signature mismatch on tokens that look correct, the first thing to check is the byte count of the secret, especially when characters from outside ASCII are involved.

An alg mismatch is the second. A token minted with HS256 will fail verification if the verifier is configured for HS384, HS512, or an asymmetric algorithm, even when the secret happens to be the same string. Keep algorithm allowlists explicit on both sides, and reject any token whose protected header lists alg: none.

A claim confusion is the third. Mixing up issuer and audience, or reusing a single test secret across multiple tenants, produces tokens that look fine in isolation and fail in production. The generator will not warn you about those policy mistakes; the verifier will.

A clipboard leak is the fourth. Copying a token exposes it through clipboard history, screenshots, browser extensions, support tickets, and chat logs. The same applies to the secret. Use only non-production claims and secrets on this page, and rotate any value that ever touched an environment outside its intended boundary.

If you're weighing options, JavaScript Key Code Finder Alternative: Local Capture covers this in detail.