Webhook Signature Verifier

Verify incoming webhook signatures instantly using local HMAC computation.

Ready to use Runs locally in your browser
How this tool works

Webhook signature verification is a critical security measure that prevents malicious actors from spoofing events. If you don't verify signatures, anyone with your webhook URL can send forged requests—potentially creating fake payment confirmations in Stripe, triggering unauthorized deployments from GitHub, or faking orders in Shopify. Signatures use HMAC (Hash-based Message Authentication Code) to guarantee both the authenticity of the sender and the integrity of the payload.

When debugging webhook integration failures, you often need to manually verify the raw payload and signature. Using online verification tools can be risky if they send your webhook secret or sensitive payload data to a third-party server. This Webhook Signature Verifier runs entirely in your browser using the native Web Crypto API. Your secrets, payloads, and signatures never leave your device, ensuring 100% privacy and security while you troubleshoot.

Stripe Webhooks: You need the raw request body, the Stripe-Signature header value, and your webhook endpoint secret (starts with whsec_).

This tool runs 100% in your browser; your data never leaves your device. Privacy details

Why Webhook Signature Verification Is Non-Negotiable

Webhooks are a fundamental part of modern web architecture, allowing services like Stripe, GitHub, and Shopify to notify your application when events occur in real-time. Because these requests are sent over the public internet to a publicly accessible endpoint on your server, there is inherently a risk of spoofing. If an attacker discovers your webhook URL, they could simulate a "payment successful" event, potentially tricking your system into providing services or fulfilling orders for free.

To mitigate this, providers implement webhook signatures using HMAC (Hash-based Message Authentication Code). When the provider sends a webhook, it uses a shared secret (known only to you and the provider) to generate a cryptographic hash of the payload. Your server receives the payload and the signature, uses the same shared secret to generate its own hash, and compares the two. If they match, you know the request is genuine. If you are exploring how HMAC generation works in detail, you can check out our HMAC Generator. Additionally, managing these secrets securely is critical; consider using a Secret Scanner to ensure webhook secrets aren't accidentally committed to your codebase.

How Stripe Webhook Signatures Work

Stripe has one of the most robust webhook signature implementations, designed specifically to prevent replay attacks. A replay attack occurs when an attacker intercepts a valid webhook request (including its valid signature) and resends it later to trigger the same action multiple times.

Stripe prevents this by including a timestamp in the signature calculation. The Stripe-Signature header typically looks like this: t=1492774577,v1=5257a869.... Here, t is the Unix timestamp of when the event was sent, and v1 is the HMAC-SHA256 signature.

To verify a Stripe webhook, you must:

  • Extract the timestamp and the signature from the header.
  • Concatenate the timestamp and the raw request body, separated by a period (e.g., timestamp.payload).
  • Compute the HMAC-SHA256 hash of this concatenated string using your endpoint secret (which usually starts with whsec_).
  • Compare the computed hash to the provided v1 signature.
  • Check that the difference between the current time and the timestamp is within your allowed tolerance (usually 300 seconds).

GitHub Webhook Signatures: SHA-256 vs SHA-1

GitHub allows you to configure a secret for your organization or repository webhooks. When an event triggers, GitHub computes an HMAC signature of the raw payload using this secret.

Historically, GitHub provided this signature in the X-Hub-Signature header using the SHA-1 algorithm. However, due to the vulnerabilities associated with SHA-1, modern implementations use SHA-256. The secure signature is provided in the X-Hub-Signature-256 header, prefixed with sha256= (for example, sha256=7d38cdea...).

Unlike Stripe, GitHub does not embed a timestamp directly into the signature header to prevent replay attacks. Therefore, it is up to your application to implement idempotency (ensuring that processing the same event ID multiple times does not result in duplicate actions). When developing custom API integrations, you might also want to generate test keys using our API Key Generator.

Shopify Webhook HMAC Verification

Shopify secures its webhooks by computing an HMAC-SHA256 hash of the raw request body using your app's client secret. They encode this hash in Base64 rather than hexadecimal, which is a common stumbling block for developers used to Stripe or GitHub.

The signature is sent in the X-Shopify-Hmac-Sha256 HTTP header. To verify it, you simply compute the HMAC-SHA256 of the raw body using your app secret, encode the result in Base64, and ensure it matches the header. Because it is sensitive to the exact byte structure, parsing the payload as JSON and then stringifying it before verification will almost always result in an invalid signature. If you ever need to inspect what headers are being sent in your environment, our HTTP Header Analyzer can be a helpful debugging tool.

Common Reasons Webhook Signatures Fail

Debugging failed webhook signatures can be frustrating. Here are the most common pitfalls:

  • Modifying the Raw Body: Frameworks like Express (Node.js) or Django (Python) often automatically parse incoming requests into JSON objects. If you then stringify that object to verify the signature, the spacing, formatting, or key ordering might differ from the original raw payload, causing the hash to change. You must verify the signature against the raw, unparsed byte stream.
  • Wrong Secret Key: Ensure you are using the correct webhook secret. For Stripe, the webhook endpoint secret (whsec_...) is different from your API keys. Additionally, test environments and live environments have different secrets.
  • Timestamp Skew: For Stripe, if your server's clock is out of sync or if the webhook was delayed in transit, the timestamp might fall outside your tolerance window.
  • Encoding Mismatches: Ensure you are comparing apples to apples. GitHub uses hexadecimal strings, while Shopify uses Base64.

Building Your Own HMAC Webhook Receiver

If you are building an API that sends webhooks to your customers, implementing a robust signature system is highly recommended. Using HMAC-SHA256 is the industry standard. For added security, incorporating a timestamp like Stripe does will protect your users from replay attacks. Similar cryptographic patterns are used in JSON Web Tokens; you can explore this by using our JWT Signature Verifier.

This Webhook Signature Verifier provides a "Custom HMAC" option specifically for developers building their own integrations. You can test payloads against various algorithms (SHA-1, SHA-256, SHA-512) and encodings (Hex, Base64) to ensure your implementation generates exactly the expected output before shipping to production.

How to Use the Webhook Signature Verifier

  1. Select your webhook provider (Stripe, GitHub, Shopify, or Custom) from the top tabs.
  2. Paste the exact raw request body into the provided textarea.
  3. Paste the signature header value (e.g., Stripe-Signature, X-Hub-Signature-256) exactly as received.
  4. Enter your webhook secret (e.g., whsec_...).
  5. Click 'Verify Signature' and review whether the computed signature matches the provided one, along with any timestamp checks.

Common Use Cases

  • Debugging failed Stripe payment webhooks: When Stripe events fail verification on your server, use this tool to manually test the payload and secret to ensure everything matches up.
  • Testing GitHub Actions webhook triggers: Verify that incoming GitHub organization or repository webhooks are correctly signed before they trigger internal CI/CD pipelines.
  • Verifying Shopify order webhooks: Ensure that 'orders/create' webhooks from Shopify are valid and not spoofed by a malicious third party before processing fulfillment.
  • Building custom webhook receivers: Use the custom HMAC verifier to test your own webhook dispatch system and ensure your internal services are generating signatures correctly.
  • Learning how HMAC-based authentication works: Experiment with raw payloads, secrets, and headers to understand the mechanics of HMAC signature generation and verification.
  • Auditing webhook security implementations: Verify that existing webhooks across your infrastructure correctly validate signatures, testing what happens when payloads are subtly altered.

Frequently Asked Questions

How does Stripe webhook signature verification work?

Stripe uses HMAC-SHA256 to sign webhook payloads. They include a 'Stripe-Signature' header which contains a timestamp ('t') and a signature ('v1'). The signature is generated by computing the HMAC-SHA256 hash of the string 'timestamp.payload' using your webhook endpoint secret.

What is the Stripe tolerance window?

To prevent replay attacks, Stripe includes a timestamp in the signature header. The tolerance window is the maximum acceptable difference between the timestamp in the header and the current time. The default is typically 300 seconds (5 minutes). If the timestamp is older than this, the webhook should be rejected even if the signature is valid.

How do GitHub webhook signatures differ from Stripe?

GitHub signs the raw payload using HMAC-SHA256 (or SHA-1 for older configurations) with your webhook secret. The signature is sent in the 'X-Hub-Signature-256' header (e.g., 'sha256=...'). Unlike Stripe, GitHub does not include a timestamp in the header to prevent replay attacks out of the box.

Why is my webhook signature invalid?

Common reasons include: using the wrong secret (e.g., test vs live mode secrets), modifying the raw request body before verifying (e.g., parsing it as JSON first), or timestamp expiration (for Stripe). The payload must be the exact raw byte string received from the provider.

Can I verify Shopify webhooks with this tool?

Yes, Shopify signs webhooks using HMAC-SHA256 with your app's client secret. The signature is Base64 encoded and passed in the 'X-Shopify-Hmac-Sha256' header. This tool allows you to verify Shopify webhooks instantly.

What HMAC algorithm does each provider use?

Stripe, modern GitHub, and Shopify all use HMAC-SHA256. GitHub historically used HMAC-SHA1 (in the 'X-Hub-Signature' header), but SHA-256 is recommended. Custom implementations might use SHA-256, SHA-384, or SHA-512 with Hex or Base64 encoding.

Why should I verify webhook signatures?

If you don't verify signatures, anyone who knows your webhook URL can send spoofed requests, potentially creating fake payments, triggering unauthorized deployments, or corrupting your data. Signature verification guarantees that the request genuinely came from the expected provider and hasn't been altered.

Related Tools