Console :3000
- Landing /
- Open console
- Playground → routedFetch
Country or city targeting, a JSON fetch API, an HTTP gateway, and sticky sessions — one selectRoute kernel. Bring your own pool or backconnect.
The models and the harnesses people actually run — Hermes Agent, OpenClaw, Claude Code, Cursor, and the rest of the stack. Drop in a fetch tool or point a browser at the gateway.
You ask for a country or city. IP Router picks an exit there, sends the request out through that IP, and hands the page back. Same brain for a JSON agent and a real browser.
It sees the exit IP. Change the exit, change the page — prices, SERP, store locator, paywall, all of it.
cc-JP puts you on a Japanese IP. lang-ja tells the site you read Japanese. You usually want both.
Logins, carts, and cookies die if the IP flips mid-flow. A sessid pins you to one exit until it expires.
Agents POST JSON to /api/v1/fetch. Browsers and curl talk CONNECT on :7777. Both call selectRoute.
Google (and Bing, and maps) do not show one internet. They show the internet from where you are standing. Rankings, the local pack, ads, even which spelling they think you meant — all of that keys off the exit IP and the language header. If your agent fetches from a US datacenter, you are grading a US result page, even when the question is “what does this look like in Manchester.”
Exact city on a non-direct pool node wins first after sticky.
Session set → hashPick(nodes, session). Else Math.random().
finish() upserts the session and, for backconnect, rewrites the vendor username.
If targeting.type is set, keep that class when any node matches; otherwise keep the full enabled set. Direct nodes can still satisfy geo as a last resort.
Source: src/lib/router.ts selectRoute. City matching via cityMatches in src/lib/geo.ts.