Webhook Signature Verifier
Check a Stripe, GitHub, Shopify, Slack or Twilio webhook signature against the raw body and signing secret, and see exactly why it fails. Computes real HMAC in the browser using the Web Crypto API.

Output will appear hereA webhook signature that will not validate is almost always a body-encoding problem rather than a wrong secret. Paste the raw payload, the signature header and your signing secret, and this tool computes the expected HMAC the way the provider does, then tells you exactly where the two diverge.
What this tool does
Every serious webhook provider signs its requests so you can prove the payload came from them and not from someone who guessed your endpoint URL. The verification recipe differs per provider, and when it fails the error message is always the same unhelpful "signature mismatch".
Paste the raw request body, the signature header and your signing secret, choose the provider, and this tool computes the expected signature using the same algorithm, the same canonical string and the same encoding the provider uses. It shows you the computed value next to the received value, and flags the specific reason they differ.
The HMAC is real, computed in your browser with the Web Crypto API's SubtleCrypto.sign(). Nothing is transmitted.
A worked example
A Stripe endpoint keeps returning 400. You copy the Stripe-Signature header, which looks like t=1712345678,v1=5257a869e7…, along with the exact bytes of the request body and your whsec_… secret.
The tool splits the header into timestamp and v1 scheme, rebuilds the signed payload as timestamp.body, runs HMAC-SHA256 with your secret, and compares. If the computed digest matches, the signature was fine and your problem is the timestamp tolerance. If it does not, you have almost certainly re-serialised the body somewhere in your stack.
How each provider signs
| Provider | Header | Signed string | Algorithm and encoding |
|---|---|---|---|
| Stripe | Stripe-Signature |
timestamp + . + raw body |
HMAC-SHA256, hex |
| GitHub | X-Hub-Signature-256 |
Raw body | HMAC-SHA256, hex, sha256= prefix |
| Shopify | X-Shopify-Hmac-SHA256 |
Raw body | HMAC-SHA256, base64 |
| Slack | X-Slack-Signature |
v0:timestamp:body |
HMAC-SHA256, hex, v0= prefix |
| Twilio | X-Twilio-Signature |
URL + sorted POST params | HMAC-SHA1, base64 |
Where people go wrong
Verifying against a parsed body. This is the cause of most failures. Frameworks parse JSON before your handler runs, and re-serialising that object produces different bytes — different key order, different whitespace, different unicode escaping. You must capture the raw body before any parser touches it. In Express that means a raw body parser on the webhook route only; in FastAPI it means await request.body() rather than the parsed model.
Comparing strings with ==. Use a constant-time comparison. A naive comparison leaks timing information that, given enough attempts, narrows down a valid signature. Every provider's own library does this for you, which is a good argument for using it.
Skipping the timestamp check. A valid signature on a replayed request is still a valid signature. Reject anything outside a tolerance window — five minutes is the usual figure — otherwise a captured request can be replayed indefinitely.
Trimming or re-encoding the payload. A trailing newline is part of the body. So is the exact character encoding. Anything that normalises whitespace between the wire and your HMAC breaks it.
FAQ
Does my signing secret leave the browser?
No. The HMAC is computed locally with the Web Crypto API. There is no network request, which is what makes it reasonable to paste a live whsec_ value.
The signature matches here but fails in my app. Why?
Almost always because your app is not hashing the same bytes. Log the raw body length in your handler and compare it against the length shown here — a difference of one or two characters usually means a parser or a proxy has touched it.
Which providers are supported?
Stripe, GitHub, Shopify, Slack and Twilio, plus a generic mode where you choose SHA-256 or SHA-1, hex or base64, and supply your own signed-string template for providers not listed.
Should I use this in production?
No. This is a debugging aid. In production, use the provider's own SDK — Stripe's webhook documentation, GitHub's guide to validating deliveries, Shopify's verification guide and Slack's request verification docs all publish the canonical implementation.
Why does Twilio use SHA-1?
Historical reasons. Its scheme concatenates the full request URL with the POST parameters sorted by key, then signs with HMAC-SHA1 and base64-encodes the result, which is why a URL mismatch behind a proxy is such a common cause of Twilio failures.
Next steps
If you are building the receiving end, Python FastAPI Webhook Automation covers capturing the raw body correctly, and the n8n Webhook Tutorial covers the no-code equivalent. To turn a documented cURL example into a working request, use the cURL to n8n converter.
Webhooks failing intermittently in production? Book a discovery call.

Want this built against your real numbers?
A 30-minute call to scope the workflow, agent, or automation you actually need.
More developer tools
All tools.env Manager
Validate, compare, and generate templates for your .env files — without exposing secrets
.gitignore Generator
Build a .gitignore for your stack in seconds. Covers dependencies, build output, IDE files and the .env patterns that keep secrets out of a public repository.
API Mock Server
Create a live mock REST endpoint with your own path, method, status code, headers, delay and JSON body — so you can build and test a frontend or automation before the real API is ready.
API Request Tester
Send REST API requests from your browser with custom headers, auth and a JSON body, and inspect the status, headers and response. Includes a guide to reading status codes and diagnosing CORS.
Base64 Encoder/Decoder
Encode or decode any Base64 string instantly — no install, no login
Cron Expression Generator
Build cron expressions visually and get the correct string for crontab, GitHub Actions, EventBridge, Kubernetes, Make or n8n — with a field reference and the common gotchas explained.
Have a workflow that's burning hours every week?
Bring me one real bottleneck. I'll tell you whether it's worth automating, and what it would take.