Skip to content
Developer Tools

Local Proxy

Forward requests from your public catcher URL to localhost via ngrok or any tunnel. Debug webhooks directly on your local machine.

Free to use
No signup
Uses a hosted service · How your data is handled

Requests are stored by the hosted Request Catcher, then forwarded to the configured URL when enabled. Bin IDs are shared with Request Catcher and saved in this browser. Anyone with an ID can change forwarding settings; no owner authentication is implemented. No automatic retention cleanup is implemented. Use synthetic test data only.

Endpoint: https://rhqvqvkkrsdvcrmvlise.supabase.co/functions/v1/request-catcher

Proxy Inactive
Endpoint ID:
Loading...

This endpoint ID is shared with the Request Catcher. Requests sent to the URL above will be captured there and forwarded here.

Forward Target

Every request received at your catcher URL will be forwarded to the target below in real-time — headers, body, method, and path all preserved. Use a tunnel URL to reach your localhost, or any public HTTPS URL.

For localhost: paste the ngrok/tunnel public URL. For production: paste any HTTPS URL.

Forwarding disabled
Expose Localhost via Tunnel

Our edge servers cannot reach your localhost. These free tools create a secure public tunnel to your local port. Run one, copy the public URL, and paste it in the Forward Target above.

1Install
brew install ngrok # or download from ngrok.com
2Start tunnel (replace 3000 with your port)
ngrok http 3000
3Copy the public HTTPS URL it prints
4Paste into Forward Target above and click Save Config

A free ngrok account is required. Sign up at ngrok.com and run: ngrok config add-authtoken <token>

5Send a test request to your catcher URL
curl -X POST "" \
-H "Content-Type: application/json" \
-d '{"test":"forwarded"}'

After sending, open the Request Catcher to see the captured request and its forward response.

About the Local Proxy

You are building a webhook handler. It runs on your laptop at localhost:3000. The provider that needs to call it lives on the internet and cannot see your laptop.

That gap is the single most tedious part of integration work, and it is what tunnelling solves: a public URL that forwards to a port on your machine.

This page manages the receiving end - a public endpoint you can point a provider at, with forwarding to a URL you nominate. The actual tunnel from the internet to your laptop needs a tunnelling client such as ngrok, cloudflared or localtunnel running locally, because a web page cannot reach your loopback interface.

Why a browser cannot do this on its own

It is worth understanding the constraint rather than fighting it.

A page on a public site cannot make requests to localhost on your machine. Browsers block it, and increasingly so - private network access restrictions exist specifically to stop a public page probing the machine it runs on. That is a good protection and you would not want it removed.

There is also nothing to route to. Your laptop is behind NAT and a firewall; it has no address the internet can reach. Something has to open an outbound connection from your machine and hold it open, so traffic can come back down it.

That is exactly what a tunnelling client does. It runs locally, connects out to a relay, and the relay gives you a public URL. This page complements that rather than replacing it.

The three things that go wrong

The Host header. Your local server receives a request whose Host is the tunnel's domain, not localhost. Frameworks with host validation - Django's ALLOWED_HOSTS, Rails' host authorisation - reject it outright, and the error is usually a blunt refusal rather than an explanation. Most tunnelling clients have an option to rewrite the Host header, and turning it on is normally the fix.

HTTPS to HTTP. The public URL is HTTPS; your local server is plain HTTP. Anything constructing absolute URLs from the request will build http:// links, and OAuth redirect URIs in particular will not match what you registered. Look for the X-Forwarded-Proto header and trust it.

The URL changing. Free tunnels usually issue a new random subdomain each time you restart, which means re-registering it with the provider every session. If you are doing this daily, a reserved subdomain is worth the cost purely in saved re-configuration.

  • Rewrite the Host header, or your framework will reject the request.
  • Trust X-Forwarded-Proto, or you will generate http:// links behind an https:// URL.
  • Expect the public URL to change on restart unless you have a reserved one.

A tunnel is a hole in your machine

For the duration, anything on the internet that knows the URL can reach the service on that port. Not just the provider you set it up for.

Tunnel URLs get scanned. Random subdomains are discovered by crawlers and by certificate transparency logs faster than people expect, and a development server is exactly the sort of thing that has debug endpoints, verbose error pages, seeded credentials and no rate limiting.

So: tunnel the specific port you need and nothing else, never point one at a database or an admin interface, use whatever authentication your tunnelling client offers, and shut it down when you stop working. Leaving one running overnight because you might need it tomorrow is how development databases end up on the internet.

The sequence that works

Catcher first. Point the provider at a request catcher and confirm it is actually sending, and see what the payload looks like. That eliminates half the possible causes before you touch your own code.

Then tunnel. Once you know requests are being sent and you know their shape, forward them to your local handler and work on what your code does with them.

Doing it the other way round means debugging your handler against a provider that may not be sending anything, which is where the wasted afternoons come from.

The Host header rejection

Input
Local server: Django on localhost:8000
Tunnel URL:   https://a3f9-2401-8c2.ngrok-free.app
Output
Request arrives at the local server:
  Host: a3f9-2401-8c2.ngrok-free.app
  X-Forwarded-Proto: https

Django response:
  400 Bad Request
  Invalid HTTP_HOST header. You may need to add
  'a3f9-2401-8c2.ngrok-free.app' to ALLOWED_HOSTS.

Fix: run the tunnel with host rewriting, or add the
host to ALLOWED_HOSTS for local development only.

This is the first thing that happens to almost everyone, and the error is at least self-explanatory - many frameworks are less helpful. Note the X-Forwarded-Proto header in the same request: that is the one to trust when building absolute URLs, because the request reaching your server is plain HTTP even though the caller used HTTPS.

What this tool will not do

  • This does not create the tunnel. Reaching a port on your own machine requires a tunnelling client running locally - ngrok, cloudflared, localtunnel or similar.
  • The endpoint and forwarding state live on a server, so this part is not client-side and the URL should be treated as public.
  • Requests to loopback and private network addresses are blocked from the public proxy, which is a deliberate protection against server-side request forgery.
  • A tunnel exposes your local service to anyone who finds the URL. Point it at one port, authenticate it if you can, and close it when you finish.
  • Free tunnel subdomains typically change on every restart, which means re-registering the URL with the provider each session.

Frequently Asked Questions

What is Local Proxy?

Local Proxy forwards every request received at your Request Catcher URL to a target URL you specify — such as your ngrok tunnel pointing to localhost. It acts like a transparent reverse proxy.

Why can't I just forward directly to localhost?

Our edge servers cannot reach your machine's localhost. You need a tunnel tool (ngrok, localtunnel, cloudflared) to create a public URL that routes to your local port.

Does it use the same endpoint as the Request Catcher?

Yes. Both tools share the same endpoint ID stored in your browser. Configure forwarding here, then visit the Request Catcher to watch requests arrive and see forward responses.

What happens if my local server is down?

The request is still captured by the Request Catcher. Forwarding will fail gracefully and log an error message visible in the Forward tab of each request.

Is there a request size or rate limit?

Forwarding has a 15-second timeout per request. Response bodies over 10KB are truncated in the display but the full request is always forwarded to your server.