Test Webhooks Locally
Two approaches
When testing webhooks locally, you typically choose between:
- Provider CLI — tools like
stripe listenthat forward events without a public URL - HTTPS tunnel — a public URL (e.g. LocalToLink) that providers can POST to directly
Both are valid. Use the provider CLI for quick iteration; use a tunnel when you need the exact production webhook URL in the provider dashboard.
Quick start with LocalToLink
# Terminal 1: your app
npm run dev
# Terminal 2: tunnel
npx localtolink --port 3000
Copy the public URL (e.g. https://k7m2x9p4q1.localtolink.com) and register it as your webhook endpoint in the provider dashboard:
https://k7m2x9p4q1.localtolink.com/api/webhooks/stripe
Webhook POST requests bypass the browser interstitial — no special headers needed for server-to-server calls.
Provider-specific guides
| Provider | Guide | |----------|-------| | Stripe | Test Stripe Webhooks Locally | | GitHub | Test GitHub Webhooks on Localhost | | Shopify | Test Shopify Webhooks in Development | | Twilio | Test Twilio Webhooks Locally | | n8n | n8n OAuth and Webhooks on Localhost |
Tips for reliable webhook testing
- Use
--portif you have multiple apps running - Use
--jsonin CI to capture the URL programmatically - Sessions last 2 hours — restart the tunnel if it expires mid-test
- Rate limit is 10 req/s per tunnel — sufficient for normal webhook traffic
- LocalToLink has no request inspector — log payloads in your handler or use the provider's dashboard
When a tunnel is not needed
Some providers ship local forwarding tools:
- Stripe CLI:
stripe listen --forward-to localhost:3000/webhook - GitHub CLI: limited webhook support; tunnel is often simpler
See Stripe webhooks guide for when to use each approach.
Try it now
Start a tunnel from your project directory — no account required.
$ npx localtolink