Reuse a Proxy Across Requests
Learn how to keep the same proxy exit across follow-up requests, so JavaScript renders, API calls, and paginated fetches all leave from the same IP.
Why Reuse a Proxy
When you first hit a target, FourA picks a working proxy for you. Every response includes the proxy ID it used. Pass that ID back on later requests and:
- Follow-up pages land through the same exit, so session cookies and rate limits stay coherent to the target.
- A country-scoped fetch stays inside your allowlist without a fresh selection.
- The cheap
POST /api/single/endpoint replays through a proxy you already paid to discover, at Single's cost instead of Proxy's.
The proxy ID is an opaque base36 string (something like A1B2C3). Never a raw IP.
Where the ID Lives in a Response
| Endpoint | Field | When it's present |
|---|---|---|
POST /api/auto/ |
session.proxy |
When returnSession is true (the default) |
POST /api/single/ |
proxy (top level) |
Only when the request supplied a proxy field |
POST /api/proxy/ |
proxy (top level) |
Always, on success |
POST /api/browser/ |
proxy (top level) |
Only when the request supplied a proxy field |
To grab a fresh exit without pinning one, start with Auto or Proxy. Both discover a working exit and return its ID for you.
Pattern 1: Auto discovers, Single replays
Best when you have a target you don't know yet. Auto walks the ladder once, then Single reuses the winning session for every follow-up page.
import requests
API = "https://eu.api.foura.ai"
H = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
# Step 1: discover a working exit with Auto.
r = requests.post(f"{API}/api/auto/", headers=H, json={
"url": "https://example.com/product/42",
"validate": {"data": {"accept": ["Add to cart"]}}
}).json()
session = r["session"]
proxy = session["proxy"]
user_agent = session["userAgent"]
# Step 2: paginate with Single, reusing the same exit and User-Agent.
for sku in ("43", "44", "45"):
p = requests.post(f"{API}/api/single/", headers=H, json={
"method": "GET",
"url": f"https://example.com/product/{sku}",
"proxy": proxy,
"headers": [["User-Agent", user_agent]],
}).json()
print(sku, p["status"])
The Auto call costs whatever its ladder spends. Every follow-up Single call costs 2 credits (Single with unblocker, the default).
Pattern 2: Proxy discovers, Browser renders through the same exit
Use this when the target must see a specific exit country and the final content needs JavaScript.
# Step 1: pick a country-scoped exit with Proxy.
curl -X POST https://eu.api.foura.ai/api/proxy/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"maxTries": 5,
"exitCountries": ["FR", "GB"],
"request": {"method": "GET", "url": "https://example.com/pricing"}
}'
# Response includes: "proxy": "A1B2C3", "exitCountry": "FR"
# Step 2: render the JS-heavy page through THAT exit.
curl -X POST https://eu.api.foura.ai/api/browser/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/pricing",
"proxy": "A1B2C3",
"timeout_ms": 20000
}'
Do not call /api/proxy/ again to refresh the selection. A new call may pick a different exit and defeat the point of pinning. If the pinned exit stops working, run a fresh /api/proxy/ call to pick a new one, then continue with that.
Pattern 3: Skip a burned exit
If an exit that used to work starts returning refusals or verification pages, tell FourA to avoid it on the next selection.
{
"maxTries": 5,
"ignoreProxies": ["A1B2C3"],
"request": { "method": "GET", "url": "https://example.com/data" }
}
ignoreProxies accepts a list of proxy IDs from earlier responses. It works on /api/proxy/ and /api/auto/. The list is honored on every internal retry, so a single call with ignoreProxies never picks the burned exits.
How Long a Pinned Session Stays Alive
The exit itself lives as long as the underlying proxy is healthy, typically minutes to hours. If a replay starts returning challenges, blocks, or unexpected redirects, the exit was probably rotated out or the target refreshed its clearance.
Two options when that happens:
- Fresh
/api/auto/call for the same URL. Auto will discover a new working session; drop the previous IDs. - Fresh
/api/proxy/call withignoreProxies: ["<burned-id>"]if you want to keep pinning manually.
Session cookies from an Auto response also expire on the target's own schedule. Some sites bind clearance for hours; others for minutes. Treat the session as a cache, not a durable token.
When an ID Won't Pin
Three 400s can come back from a proxy value, and they mean different things:
| Error | What happened | What to do |
|---|---|---|
Invalid proxy format |
The value isn't an ID FourA issued. A raw proxy address lands here. | Send the opaque string from a response, verbatim. |
Proxy not found |
The ID decoded, but it no longer resolves to a live exit. | Take a fresh exit from a new Auto or Proxy call. |
Managed exit: this proxy id cannot be pinned to a request |
The ID is a premium exit, and your plan's premium traffic for this period is used up, or your plan doesn't include premium exits. | Run the call through POST /api/proxy/ and take whichever exit it picks, or add premium traffic and pin it again. |
The third one comes back from an ID a successful call handed you, so you can hit it without having done anything wrong. Treat it the way you'd treat an expired session: fall back to a fresh discovery call rather than retrying the same ID.
Common Mistakes
- Reusing a proxy ID across accounts. Don't share IDs between accounts: an ID one account can pin may be refused for another, for example a premium exit on a plan without premium traffic.
- Trying to decode the ID. The base36 string is opaque. Don't parse it, don't strip characters, don't lowercase it. Pass it back verbatim.
- Pinning through a rate-limited exit. If the target rate-limits per IP, funneling many requests through one exit will trigger blocks faster. For high-volume workloads, let Auto or Proxy rotate through many exits and pin only where the target genuinely requires it.
- Pinning a premium exit without meaning to. An ID from a call a premium exit served (
exitClass: "premium"on Proxy) pins that premium exit. Every replay through it counts against your premium traffic, and the response carriesX-FourA-Exit-Class: premium. - Sending
exitCountrieson a plan without geo targeting. Country scoping is included from the Startup plan up. On a plan without it, a call that sendsexitCountriesis refused with a403andX-FourA-Limit: plan_limit_feature. - Ignoring
exitCountrieson the follow-up. If you pin a scoped exit and then call Proxy again withoutexitCountries, the follow-up may land through a different country. Keep the scope on every call that needs it.
Related
- API Endpoints: Full parameter and response reference
- Smart Fetch (Auto): How Auto builds the session you replay
- Protected sites: When pinning helps and when rotation is better
- Common Issues:
no_eligible_proxyand other proxy errors - Why a Proxy Request Ran Out of Tries: Reading
attemptReportwhen a Proxy call gives up