What is a tunnel (localhost tunnel)? How it works

A localhost tunnel gives a server running on your machine or a private network a public URL. An agent on your side opens an outbound connection to a tunnel service, and the service relays any request sent to the public hostname back down that connection to your local port. Your server becomes reachable from the internet without a public IP, port forwarding or firewall changes.

relay connect --name my-app http://localhost:3000
# prints a public HTTPS URL that forwards to http://localhost:3000

How a tunnel works

  1. You start your app on a local port, for example localhost:3000.
  2. You run the tunnel agent. It makes an outbound TLS connection to the tunnel service. Outbound connections pass through NAT and most firewalls, so nothing inbound needs to be opened.
  3. The service assigns a public hostname and terminates HTTPS for it.
  4. A browser or API client requests the public URL. The service forwards the request over the open connection.
  5. The agent sends it to localhost:3000, takes the response and streams it back the same way.

In effect, the tunnel service is a reverse proxy on the internet whose upstream happens to be your laptop.

browser ──HTTPS──▶ tunnel service (public hostname, TLS)
                        ▲
                        │ outbound connection opened by the agent
                        │
your machine:      tunnel agent ──▶ http://localhost:3000

What tunnels are used for

  • Showing work in progress to a client or teammate without deploying.
  • Testing on real devices. Open your local site on a phone over HTTPS.
  • Callbacks and OAuth redirects that need a public HTTPS URL. See callback URL.
  • Receiving webhooks during development.
  • Reaching a service with no public IP, such as a home server, a Raspberry Pi or an internal dashboard.
  • TCP services like SSH or a database, with a TCP tunnel instead of HTTP.

Tunnel vs webhook forwarding

For webhooks specifically, webhook forwarding is often the better tool:

TunnelWebhook forwarding
ExposesThe whole port, any pathOnly webhook requests to one URL
Machine offlineRequests fail (usually a 502 or 504)Requests are stored and retried or replayed
One URL, many destinationsNoYes
Interactive browsingYesNo

Webhook Relay offers both: relay connect for tunnels and relay forward for webhook forwarding.

Common pitfalls

  • The URL changes on every restart. Many free tunnel tools assign a random hostname each time, so every webhook or OAuth setting must be updated. Use a tool that keeps a stable name. With Webhook Relay, reusing --name keeps the same address.
  • Host header mismatches. Dev servers like Vite and webpack reject requests whose Host is not localhost ("Invalid Host header" or "Blocked request"). Allow the tunnel hostname in the dev server config, or have the tunnel rewrite the Host header.
  • Certificate errors. If the tunnel forwards to https://localhost with a self-signed certificate, the agent may refuse it. Point the tunnel at the plain http:// port and let the service terminate public TLS. A self-signed certificate exposed directly to browsers causes ERR_CERT_AUTHORITY_INVALID.
  • Binding to the wrong interface. If the agent runs in Docker, localhost means the container. Use the host's address or the service name.
  • Leaving it open. A tunnel to a dev server with debug endpoints is a public attack surface. Add authentication and stop it when you're done.
  • Latency. Traffic goes via the tunnel service. Pick the region closest to your users; Webhook Relay tunnels run in multiple regions.

See tunnels for setup, or demoing your website for a walkthrough.

Frequently asked questions

What is a localhost tunnel?

A localhost tunnel gives a server running on your machine or private network a public URL. An agent on your machine opens an outbound connection to a tunnel service, and the service relays requests from the public URL back over that connection to your local port, so no firewall port or public IP is needed.

Are tunnels safe?

A tunnel makes your local server reachable by anyone who knows the URL, so treat it like a public deployment. Don't expose admin panels or databases without authentication, prefer HTTPS, close the tunnel when you're done, and be aware that some tunnel URLs are guessable or listed in logs.

What is the difference between a tunnel and a VPN?

A VPN connects a device into a private network so it can reach many internal hosts. A localhost tunnel goes the other way and exposes one specific local service to the public internet through a hostname. VPNs are for private access; tunnels are for public access to one port.

Should I use a tunnel or webhook forwarding for webhooks?

Either works, but webhook forwarding is usually better for webhooks. A tunnel exposes the whole port and drops requests when your machine is offline. Webhook forwarding only relays webhook requests, can store and retry them while you are offline, and can deliver one webhook to several destinations.