Skip to content

HMAC Signature Tester for Webhooks (SHA-1/256/512)

Compute and compare HMAC-SHA1/256/512 signatures for GitHub, Stripe, Shopify, Meta and Slack webhooks, entirely in your browser via WebCrypto.

Runs in your browser; nothing is uploaded.

Runs in your browser; the secret and message are never sent anywhere.

Algorithm
Output
0 bytes (UTF-8)

How to use it

How to test a webhook's HMAC signature

  1. Enter the shared secret your webhook provider gave you, and choose how it's encoded (most providers give you a plain UTF-8 string; a few give hex or base64).

  2. Paste the exact raw bytes of the request body the provider signed — reformatting JSON, even just changing whitespace, produces a different signature.

  3. Pick the algorithm (HMAC-SHA1, SHA-256 or SHA-512) and the output encoding (hex or base64) your provider uses.

  4. Use a preset button (GitHub, Stripe, Shopify, Meta, Slack) to set the algorithm and output automatically, and to see which header carries the signature and how it's formatted.

  5. Paste the signature value you received into Compare against a received signature — the tool tells you whether it matches, and flags a mismatch that's really just extra whitespace or a trailing newline.

Some providers don't sign the body alone. Stripe signs <timestamp>.<raw body> and Slack signs v0:<timestamp>:<raw body> — the relevant preset fills in an editable template for the message field so you can drop in the real values.

Everything runs locally using the WebCrypto API built into your browser. The secret and message are never sent anywhere, logged, or stored.

Frequently asked questions

Why doesn't my signature match even though the secret is right?

The most common cause is signing a re-serialized copy of the JSON body instead of the exact raw bytes the provider sent — different whitespace, key order, or a trailing newline all change the HMAC. Sign the literal request body, not a reformatted version of it.

What's the difference between the GitHub and Stripe conventions?

GitHub (and Meta) HMAC the raw body alone and send it as "sha256=<hex>". Stripe HMACs "<timestamp>.<raw body>" (a literal dot) and sends "t=<timestamp>,v1=<hex>", specifically to prevent replaying an old, validly-signed request.

Should I use SHA-1, SHA-256, or SHA-512?

Use whichever your provider documents — you can't choose it independently. Most current APIs (GitHub, Stripe, Shopify, Meta, Slack) use HMAC-SHA256. Some legacy integrations still send an HMAC-SHA1 signature alongside it for backward compatibility.

Why does a trailing newline change the result?

HMAC treats its input as an exact byte sequence, not text with meaning. A message ending in \n has one more byte than the same text without it, so the two produce completely different signatures even though they "look" the same in an editor.