Receive webhooks on localhost — no tunnel needed

Your app runs on http://localhost:3000, but GitHub/Stripe/Slack can only deliver webhooks to a public URL. The usual answer is a tunnel (ngrok, cloudflared, localtunnel) — which means installing a daemon, keeping a session alive, and on many corporate networks it's blocked outright. There's a simpler way: capture the webhook at a public bin, and relay it to localhost by polling from your side.

1. Create a bin and point the provider at it

$ curl https://catchhook.catchhook.workers.dev/new

Paste the /h/… capture URL into the provider's webhook settings (GitHub repo → Settings → Webhooks, Stripe → Developers → Webhooks, …).

2. Run the relay on your machine

$ curl -s https://catchhook.catchhook.workers.dev/cli -o catchhook && chmod +x catchhook
$ ./catchhook relay YOUR_BIN http://localhost:3000

That's it. Every webhook that hits your bin is re-delivered to your local server within a couple of seconds, with:

By default only new captures are relayed; add --all to replay the bin's history too (handy to re-run a batch of deliveries against a fresh build).

Why polling beats a tunnel here

The trade-off: delivery adds a second or two of latency, and the webhook sender sees the bin's response (customisable in settings), not your local server's. For inspecting and developing handlers that's usually exactly what you want — the provider always gets a clean 200 while your handler is allowed to crash.

Scripting it yourself

The relay is plain HTTP; you can build your own in any language:

# list new captures (tab-separated: id, method, path?query)
curl 'https://catchhook.catchhook.workers.dev/api/bins/YOUR_BIN/relay-list?after=0'

# fetch one capture's raw body and forwardable headers
curl https://catchhook.catchhook.workers.dev/api/bins/YOUR_BIN/req/REQUEST_ID/body
curl https://catchhook.catchhook.workers.dev/api/bins/YOUR_BIN/req/REQUEST_ID/fwd-headers

The x-catchhook-last response header on relay-list is the cursor for your next poll; ?peek=1 returns just the current cursor so you can start "from now".

Further reading

There is a longer walk-through with real transcripts (GitHub-style HMAC verification end-to-end through the relay) on dev.to: Webhooks to localhost without ngrok (or any tunnel).

No signup needed. Or from your terminal: curl https://catchhook.catchhook.workers.dev/new

← All guides · Docs · CatchHook vs webhook.site