How to Test Webhooks Locally

· 5 min read

Testing webhooks during development is frustrating. The service sending the webhook needs a public URL, but your dev server is on localhost. Here are the most practical approaches.

The Problem

When you configure a webhook in Stripe, GitHub, or any other service, it needs to send HTTP requests to a URL it can reach. Your local machine at localhost:3000 is not reachable from the internet. You need a bridge.

Option 1: Use a Webhook Relay

The simplest approach is to use a hosted webhook endpoint that captures events and lets you view them in real time. With dread, this takes 30 seconds:

# Install dread
curl -sSL dread.sh/install | sh

# Create a channel and get your webhook URL
dread init

# Output: Your webhook URL is https://dread.sh/wh/ch_abc123
# Paste this URL into Stripe/GitHub/etc.

Now run dread to see events in your terminal as they arrive:

# Open the terminal UI
dread

# Or run in the background with desktop notifications
dread watch

Every webhook that hits your URL shows up instantly as a desktop notification and in the terminal UI where you can inspect the full payload, headers, and metadata.

Option 2: Use a Tunnel (ngrok, etc.)

Tunneling tools expose your local server to the internet:

ngrok http 3000
# Gives you a public URL like https://abc123.ngrok.io

This works, but has drawbacks:

  • Free tier URLs change every session — you must reconfigure the webhook each time
  • Your local server must be running to receive events
  • No built-in payload inspection or event history
  • Adds latency and a dependency on the tunnel service

Option 3: CLI-Specific Tools

Some services offer their own CLI for webhook testing:

# Stripe CLI
stripe listen --forward-to localhost:3000/webhooks
stripe trigger payment_intent.succeeded

# GitHub CLI (limited)
gh webhook forward --repo=owner/repo --events=push

These work well for their specific service but do not help when you need to test webhooks from multiple sources simultaneously.

Best Practices for Webhook Testing

  1. Always verify signatures — Even in development, test that your signature verification code works correctly.
  2. Log the raw payload — Do not just log parsed data. Keep the raw JSON so you can debug parsing issues.
  3. Test error scenarios — What happens when your handler returns a 500? Most services will retry, which can cause duplicate processing.
  4. Use idempotency keys — Design your webhook handler to safely process the same event twice.
  5. Check the response time — Most services expect a response within 5-30 seconds. If your handler takes longer, move the work to a background queue.

Comparing Approaches

For most developers, a webhook relay like dread is the fastest path to testing webhooks. It works across all services, persists event history, and does not require your local server to be running.

Start testing webhooks now

Get a webhook URL and terminal UI in one command.

curl -sSL dread.sh/install | sh