How to Expose Localhost with Cloudflare Tunnel

3 min read.

Testing webhooks from GitHub, Slack, Stripe, or any third-party service on localhost is painful. They need a public URL to hit, and http://localhost:3000 only works on your machine. Cloudflare Tunnel fixes this — one command, live HTTPS URL, no account required.

Install cloudflared

macOS:

brew install cloudflare/cloudflare/cloudflared

Linux (Debian/Ubuntu):

curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb

Grab the binary from the releases page if you're on something else.

Fire up the tunnel

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

A few seconds later you'll see:

+----------------------------------------------------------+
|  Your quick Tunnel has been created! Visit it at        |
|  https://cotton-steal-most-sage.trycloudflare.com        |
+----------------------------------------------------------+

That URL is live right now. Hit it and your local server gets the request.

Using it for webhooks

Copy the tunnel URL and add your webhook path.

GitHub: Repo → Settings → Webhooks → Add webhook

https://cotton-steal-most-sage.trycloudflare.com/api/webhooks/github

Stripe: Dashboard → Webhooks → Add endpoint. Same pattern. Or just use stripe listen if you're on Stripe — it handles tunneling for you.

Slack, Twilio, SendGrid — whatever service needs a callback URL, this works the same way.

Your dev server sees the webhook exactly like production would. Log the payload, drop a breakpoint, iterate without deploying.

One gotcha: the URL changes

Every time you run cloudflared tunnel --url, you get a different random subdomain. Register https://cotton-steal-most-sage.trycloudflare.com/api/webhooks/github in GitHub today, and tomorrow you'll need to update it.

That's fine for quick testing. But if you're debugging the same webhook integration over multiple days, create a free Cloudflare account and set up a named tunnel with your own subdomain. Those persist across restarts.

Also: quick tunnels have no auth. The random URL makes it hard to guess, but not impossible. For webhook testing this is usually fine — you're verifying signatures server-side anyway. Just don't leave it running overnight pointing at something sensitive.

Wrap up

cloudflared tunnel --url http://localhost:3000 gives you a public HTTPS URL in seconds. No signup, no config. Drop it into your webhook dashboard, keep the tunnel running, and test like it's production.

Latest Posts