Agent

Why Browser-Based API Clients Can't Reach Localhost (And How to Fix It)

Browser API testing tools hit a real wall at localhost and private networks — here's why that happens, and how AlleForge Agent solves it without giving up the no-install browser workflow.

AlleForge TeamAugust 16, 20264 min read

Point a browser-based API tool at http://localhost:3000 and it often just fails — not because the tool is broken, but because of something every page running in a browser tab is subject to, whether it's a testing tool or not.

The actual restriction

Browsers enforce the same-origin policy: JavaScript running on one origin (scheme + host + port) can't freely read a response from a different origin unless the target server explicitly allows it, via CORS response headers like Access-Control-Allow-Origin.

Localhost and private-network APIs usually don't send those headers at all — they were never built to be called from an arbitrary web page, so there was never a reason to add them. A hosted web app (say, one served from https://app.example.com) trying to fetch() http://localhost:3000/api/users is a cross-origin request by definition, and without permissive headers on the localhost side, the browser blocks it. Recent browser restrictions on public-to-private and private-to-local network requests tighten this further, independent of CORS entirely.

None of this is a bug in a browser-based tool. It's the browser doing exactly what it's supposed to do.

Why a desktop client doesn't hit this

An installed, native desktop API client doesn't run inside a browser tab — it makes the HTTP request directly from the operating system process, with no browser sandbox involved at all. Same-origin policy only applies to code running in a browser's JavaScript engine; a native app was never subject to it in the first place. That's the actual mechanism, not something specific to any one tool — any installed app gets this for free, and any browser tab, running any tool, doesn't.

This is the real tradeoff a browser-native API client has to solve: keep the zero-install, always-up-to-date, identical-for-everyone workflow, but stop being blocked at exactly the boundary where a desktop app was never blocked to begin with.

How Agent solves it

AlleForge Agent is a small helper you install once and start only when you need it — there's no always-on background service. Once it's running, a request to localhost, a Docker container, a Kubernetes cluster-internal service, or another private network destination doesn't try to leave the browser tab directly. Instead:

  1. Your browser tab sends the request to Agent over a local, encrypted tunnel.
  2. Agent — a native process on your machine, not subject to browser sandboxing — makes the actual request to the local or private destination.
  3. The response streams straight back through Agent to your browser tab.

Requests routed this way never pass through AlleForge's own infrastructure — the traffic goes directly from your browser to your machine and back. Latency stays close to what you'd see hitting the API directly, since it's a local tunnel, not a remote relay.

What's actually supported

  • Localhost — any local server, any port.
  • Docker — containerized services running on your machine.
  • Kubernetes — cluster-internal APIs, the same way.
  • Self-signed certificates — local HTTPS setups that a browser would otherwise refuse outright.
  • Platforms — macOS and Windows today. Linux support is coming soon, not available yet.

A concrete example

Say you're running a service locally on port 3000 and want to test GET /api/users:

1. Start Agent (only needed while you're testing local/private endpoints).
2. In AlleForge, send a request to http://localhost:3000/api/users as you
   normally would — no special configuration on the request itself.
3. Agent relays it, your local server responds, and the response shows up
   in your browser tab exactly like any other request.

If you're switching between this local server and a staging or production deployment of the same API, that's what Environments are for — same request, different {{baseUrl}}, Agent only in the loop when the target is actually local or private.

What this doesn't fix

Agent solves the browser-can't-reach-it problem specifically. It doesn't fix a server that isn't actually running, a port that's wrong, or a firewall blocking access even locally — those are still the same problems they'd be with any client, desktop or browser-based. And if you're on Linux, Agent isn't available yet.

If the local server you're testing happens to be a model server like Ollama, the same restriction applies with a few provider-specific details worth knowing — see testing local AI APIs.

See this in AlleForge

See AlleForge Agent