Free ngrok alternatives for webhook testing

ngrok is great until you hit the free-tier walls: random URLs that expire when the tunnel restarts (breaking every webhook subscription you configured), session time limits, and an account requirement. If all you need is webhooks reaching your dev machine, you have options. Here's an honest rundown — including where each one beats the others.

1. cloudflared (Cloudflare Tunnel)

$ cloudflared tunnel --url http://localhost:3000

Good: free, no account needed for quick tunnels, solid infrastructure.
Trade-offs: you get a random trycloudflare.com URL that changes every run — so you're back to re-configuring the webhook provider each time. A stable named tunnel requires an account and a domain. It's a full tunnel daemon, which some corporate networks and CI environments block.

2. localtunnel / serveo / localhost.run (SSH-based)

$ ssh -R 80:localhost:3000 nokey@localhost.run

Good: nothing to install (SSH is everywhere), no account.
Trade-offs: random URLs per session, variable reliability (these are mostly volunteer/small services and go down or rate-limit), and some inject an interstitial page that breaks non-browser webhook senders.

3. VS Code / dev-container port forwarding

Good: built into tools you already run.
Trade-offs: URLs require auth by default (webhook senders can't log in), tied to your editor session, not scriptable in CI.

4. The no-tunnel approach: capture + relay

All of the above solve "expose my laptop to the internet." But for webhooks you can flip the problem: give the provider a stable capture URL, and pull the captures down to localhost yourself.

$ curl -s https://catchhook.catchhook.workers.dev/cli -o catchhook && chmod +x catchhook
$ curl https://catchhook.catchhook.workers.dev/new          # → stable /h/… URL, paste into the provider once
$ ./catchhook relay YOUR_BIN http://localhost:3000

Every webhook that arrives is re-delivered to your local server with the original method, sub-path, query string, headers, and a byte-identical body — so HMAC signatures (GitHub's X-Hub-Signature-256, Stripe's, Shopify's) still verify in your real handler code.

Good:

Trade-offs, honestly: it's polling, so delivery to localhost lags a couple of seconds behind the original webhook — fine for development, not for exposing a production service. It only speaks HTTP (no raw TCP/TLS tunneling, no custom domains pointing at your laptop). If you need a browser to reach your local app from the internet, you still want a real tunnel; if you need webhooks, this is simpler and stabler.

Quick chooser

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

← All guides · Docs · CatchHook vs webhook.site