The website never sees your laptop
It sees the exit IP. Change the exit, change the page — prices, SERP, store locator, paywall, all of it.
Every device on the internet has an address. Search, shops, ads, and news sites use that address to decide what you see — currency, language, rankings, even whether the page loads at all. An AI agent in a datacenter has one address: that datacenter. Without a localized exit, every fetch looks like it came from one building.
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.
Pick the door that matches how your client talks. Targeting is the same either way.
Use this when your client posts JSON: an LLM tool, a script, a n8n node, the playground.
POST /api/v1/fetch with a Bearer key. Put country, city, language, session in the body. The response includes the page, the exit geo, and route.reason so you can see why that hop was chosen.
It fetches a URL and returns the body. It does not click, fill forms, or keep a real browser cookie jar. For a checkout in a real browser, use the gateway.
Use this when the client already speaks HTTP proxy: curl -x, Playwright, Chrome, a scraper that expects CONNECT.
Point the proxy at host:7777. Username is iprouter-{keyId}-cc-GB-city-london-sessid-job1. Password is the API key. Same targeting tokens as the fetch body, just in the username.
CONNECT cannot rewrite HTTPS headers. If you need Accept-Language on a TLS site, the browser (or fetch API) must send it. lang- in the username is a hint for routing and for HTTP, not a magic HTTPS inject.
| If you are | Use |
|---|---|
| JSON agent / LLM tool | Fetch API |
| Playground / try a URL | Fetch API |
| curl, Playwright, a real browser | Gateway :7777 |
| Login then crawl the same session | Either door, plus a sessid |
An exit is where the request leaves the internet as far as the website is concerned. You need at least one that is not “this machine” before geo pages will change.
Ships with the node. Requests succeed immediately so the playground works. route.reason will say “direct” or “direct fallback (no geo node)”. The website still sees your host IP.
Console → Proxy pool. Each node has a country, optional city, and a type. Ask for London; a London pool node wins. Ask for GB with no city; any GB node wins.
You add one gateway. IP Router injects targeting into the username (-cc-DE-city-berlin-sessid-s1). Use this when you buy bandwidth from a provider instead of listing every IP.
Rack Android phones, tag the site with a country and city, set how many connections are live. Agents leave through that last mile. Billed per connection per month. A 14-day trial covers the first phone.
When you name a country, the router tries in this order: city pool match → country pool match → backconnect geo injection → direct fallback. No enabled proxies at all is a 422, not a silent miss.
Do this once so the rest of the guide is not abstract. Five minutes. You do not need a paid exit yet.
Landing → Open console. Locally there is no signup. You land on Overview.
Playground is pre-filled with the local echo. Pick a country (US is fine). Leave session as agent-demo. Send. You always get a 200 from echo — this proves the door, not the geo.
ok should be true. route.reason tells you which exit was chosen. geo.exit is the IP the outside world would see — empty or your machine on direct.
Add a pool or backconnect node under Proxy pool, or an IP farm in a city you care about. Send again. reason should no longer say “direct fallback”.
API keys for the Fetch API. Endpoints builds the gateway username. Agents has the LLM tool schema. Same targeting, three skins.
Same knobs every time: country, city, language, sticky, type. The job only changes which ones you turn and which door you walk through. Pick a row.
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.”
You get the host country’s SERP. A London query from a Virginia VM is still a Virginia page with a London-shaped query string.
cc-GB + city-london + lang-en_GB. The hop leaves through a UK exit, Accept-Language is British English, and the page is the one a London visitor would get.
Fetch for snapshots the agent can parse. Gateway when Playwright is clicking through results.
{
"url": "https://www.google.com/search?q=best+coffee+near+me",
"geo": { "country": "GB", "city": "London", "language": "en-GB" },
"session": "serp-london"
}curl -x http://iprouter-key_dev-cc-GB-city-london-lang-en_GB-sessid-serp-london:ipr_live_dev_key@127.0.0.1:7777 https://www.google.com/search?q=best+coffee+near+me
route.reason is a geo hit, geo.exit is not your host, and the local pack names London businesses — not the ones next to your server.
A Japanese IP with an English Accept-Language often still serves English. Set lang (or language in the fetch body) as well as cc.
If the session string changes, you are a new person. Logins drop. Reuse the same sessid for the whole job.
A 200 from echo on this machine is not proof of geo. Read route.reason. If it says direct fallback, the website still saw your host.
Some origins fingerprint ASN. If the page is a captcha wall or a “datacenter detected” blank, set type-residential or use an IP farm.
The gateway cannot inject Accept-Language into an HTTPS CONNECT tunnel. Send the header from the client, or use the Fetch API.
If every node is disabled, you get 422 “No enabled proxies in the pool.” Enable the direct node or add one that is on.