How Do I Test Webhooks Locally?
Use ngrok (ngrok http 3000), webhook.site (free, no install), or RequestBin to receive webhooks on localhost. For production testing: set a retry policy, log payloads, verify signatures, and use HMAC validation.
Option 1: ngrok (Tunnel to Localhost)
ngrok creates a public URL that forwards traffic to your local server.
# Install ngrok (macOS)
brew install ngrok
# Start your local server on port 3000
node server.js
# In another terminal, create the tunnel
ngrok http 3000
# Output:
# Forwarding https://abc123.ngrok.io -> http://localhost:3000
Use the https://abc123.ngrok.io URL as your webhook endpoint in Stripe, GitHub, Slack, or any webhook provider. The ngrok web dashboard at http://localhost:4040 shows all incoming requests with full headers and body.
Option 2: webhook.site (No Install)
- Visit webhook.site
- Copy the unique URL it generates
- Paste it as your webhook endpoint in the service you are testing
- Trigger the event and watch the request appear in real time
Best for quick inspection when you do not need to process the payload programmatically.
Option 3: RequestBin
Similar to webhook.site but with additional features like custom responses. Create a bin, get a URL, and inspect incoming requests.
Verifying Webhook Signatures (HMAC)
Always verify webhook signatures in production to prevent tampering:
# Python example (GitHub webhooks)
import hmac
import hashlib
def verify_signature(payload_body, secret, signature_header):
expected = 'sha256=' + hmac.new(
secret.encode('utf-8'),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
Production Webhook Best Practices
- Retry policy: Return 200 quickly, process async. If you return 5xx, the sender will retry.
- Idempotency: Handle duplicate deliveries. Use the event ID to deduplicate.
- Log everything: Store raw payloads for debugging. You cannot replay what you did not save.
- Signature verification: Always validate HMAC signatures. Never trust unverified payloads.
- Timeout handling: Respond within 5-10 seconds. Queue long-running work for background processing.
Use InvokeBot to build and send test webhook payloads with custom headers, methods, and JSON bodies.