Webhook signature verifier
Verify a pasted HMAC webhook signature with local Web Crypto and omit the secret from every result.
How it works & useful details
Local-only workspace
This tool converts or inspects pasted text in your browser. It never sends a request, opens a URL, uploads a HAR, or stores your input.
HMAC signature check
The browser imports a non-extractable key for the duration of the check and compares HMAC bytes locally. The report omits the secret and computed signature. Match results only show that the supplied bytes agree; they do not establish sender identity on their own.
About this tool
Webhook signature verifier checks whether a pasted HMAC signature matches a payload, using the Web Crypto API in your browser. It supports the common provider pattern where a signing secret, a request body, and a hex or base64 signature are available.
Verification happens locally and the secret is never included in the result. That makes the tool suitable for debugging a failing webhook integration without exposing production credentials in a log or screenshot.
How to use it
- Paste the raw request body exactly as the provider sent it.
- Enter the signing secret and choose the hash algorithm used by the provider.
- Paste the received signature value and select its encoding.
- Verify to see whether the signature matches, then compare the computed value if it does not.
Worked example
With the payload {"event":"note.created","id":"note_42"}, the secret demo-webhook-secret, and HMAC SHA-256 in hex, the expected signature is:
eca86d87e73da960106e2b2a93d31a508297cd2ffa9f3d64476f479d454d51baPasting that value reports a match. Change a single character in the payload, even a space, and the result is a mismatch. That is exactly the property that makes HMAC signatures useful: any modification in transit is detected.
Why signatures fail to verify
- The payload was re-serialized. Providers sign the raw request body, so verify the exact bytes you received, not JSON that has been parsed and printed again.
- The provider signs more than the body. Stripe signs "timestamp.body" and GitHub prefixes the header value with "sha256=". Use only the hex part of the header, and build the signed string the way the provider documents.
- Wrong encoding: some providers send hex, others Base64 (Shopify and Slack use different schemes).
- Wrong secret: test and live modes usually have different signing secrets.
The secret is imported as a non-extractable Web Crypto key, used for this one check, and left out of every result. In production code, compare signatures with a constant-time comparison and reject old timestamps to prevent replay attacks.
Frequently asked questions
Is the signing secret stored or logged?
No. The secret is used for the local comparison only and is omitted from every part of the result.
Which algorithms and encodings are supported?
Standard HMAC hashes available through Web Crypto, with hex and base64 signature input. Providers using custom canonicalization may need extra steps before verification.
What is the limit?
Up to 106,000 characters across the combined inputs, which covers typical webhook payloads.
Does a valid signature prove who sent the webhook?
It proves the sender knows the shared secret. That is strong evidence if the secret is kept private, but it says nothing about the payload's contents being correct or current.
