How to Test Webhooks Locally: Complete 2026 Guide
Source: Dev.to
Introduction
Testing webhooks during local development can be tricky because your localhost isn’t reachable from the internet. Services like Stripe, GitHub, or Shopify need a public URL to deliver HTTP POST requests to your webhook endpoint.
Tunneling Tools
ngrok
ngrok http 3000
- Creates a public URL (e.g.,
https://abc123.ngrok.io) that forwards tolocalhost:3000. - Free tier URLs change on each restart; paid plans ($8‑25/month) provide stable URLs.
Cloudflare Tunnel (formerly Argo Tunnel)
cloudflared tunnel --url http://localhost:3000
- Free and integrates with existing Cloudflare configuration.
localtunnel
npx localtunnel --port 3000
- Open‑source alternative; reliability may vary.
Capture Services
Capture services act as an inbox for incoming webhooks, allowing you to inspect, store, and replay them later.
- Permanent URL – e.g.,
https://thunderhooks.com/h/my-project.
Workflow
- Configure the provider (Stripe, GitHub, etc.) to send webhooks to the permanent URL.
- Webhooks are stored (typically 7‑30 days) and can be inspected via a dashboard.
- When ready, replay the captured webhook to your local tunnel URL.
Advantages over direct tunneling
- No need to keep a tunnel alive 24/7; missed deliveries are queued.
- Easy to replay the same payload multiple times for debugging.
- Eliminates constant URL updates in provider configurations.
Trade‑off
- Two‑step process (capture → replay) instead of direct forwarding, but often worth the flexibility.
Provider‑Specific Testing Tools
Stripe CLI
stripe listen --forward-to localhost:3000/webhooks/stripe
stripe trigger payment_intent.succeeded
- Forwards live Stripe events to your local server.
- Allows you to trigger test events on demand.
- Works only with Stripe.
GitHub
- No built‑in forwarding, but you can use the GitHub API to redeliver webhooks from the settings page.
Recommended Workflow
| Scenario | Recommended Tool |
|---|---|
| Quick debugging & inspection | Capture service |
| Integration testing (specific events) | Provider CLI (e.g., Stripe CLI) |
| End‑to‑end testing with real events | Stable tunnel (ngrok paid tier, Cloudflare Tunnel) |
Development Best Practices
- Signature verification – Never skip it in development; enable it before production. See Stripe’s signature verification docs.
- Environment variables – Store webhook URLs per environment (local, staging, production).
- Idempotency – Webhooks may be delivered multiple times; ensure your handler can process duplicates gracefully. Test by replaying the same webhook.
- Timeout handling – Respond with a
2xxstatus quickly (under 30 seconds). Offload heavy processing to background jobs.
Pre‑deployment Checklist
- Handler returns
2xxstatus promptly - Signature verification is enabled
- Duplicate deliveries are handled (idempotency)
- Failures are logged with sufficient context
- Retry logic for temporary failures is in place
- Timeout handling works correctly