Proxies
The proxy gateway is the core of the platform. You point any HTTP client at a
single endpoint, authenticate with one set of credentials, and every request
egresses through a managed pool of IPs — datacenter, residential, or dynamic —
with per-request geo-targeting and optional sticky sessions. You manage one set
of credentials and nothing else, and the same credentials work from curl,
requests, Scrapy, Playwright, Go, or anything else that speaks the standard
HTTP proxy protocol.
It’s an ordinary HTTP proxy with Basic authentication. If your tool has a “proxy” setting, it already works — there is no SDK to install. You choose the network by which port you connect to, and you shape each request through the username (country and session).
Quick start
Send a request through the datacenter tier and check the egress IP:
curl -x http://USERNAME:PASSWORD@insightproxy.insightscrap.com:60000 \
https://api.ipify.org?format=jsonThe IP you get back is a proxy IP from the network you selected. Swap the port to pick a different network; add a suffix to the username to pick a country or a sticky session (both below).
Getting credentials
Create proxy credentials in the dashboard under Proxy Users. Each credential
is a username you choose and a password the platform generates.
- The password is shown once at creation (and on regeneration) — copy it then.
- Per credential, you control which tiers are enabled and each tier’s
rate limit. A tier that isn’t enabled returns
403. - Usernames may contain letters, digits,
_and-, and must be at least 3 characters.
Credentials are scoped to your organization; billing, spend caps and analytics all roll up at the org level.
Tiers and ports
The tier is selected entirely by the port you connect to on
insightproxy.insightscrap.com. There is no tier switch in the username or a
header — just the port.
| Tier | Port | Network | Reach for it when |
|---|---|---|---|
| datacenter | 60000 | Fast static datacenter IPs (single US pool). | Default choice — cheapest and fastest; targets that don’t block datacenter ranges. |
| residential | 61000 | Real residential IPs, geo-targetable, rotating. | Targets that block datacenter IPs, or when you need to appear as a home user in a specific country. |
| dynamic | 62000 | A large, constantly-rotating pool of egress IPs. | Maximum IP diversity — each request can come from a different IP across a broad surface. |
Same credentials, same auth on every port. Moving between tiers is just changing the port number — nothing else about your integration changes.
Authentication
Send standard HTTP Basic credentials in the Proxy-Authorization header.
Most clients build this for you when you put the credentials in the proxy URL
(http://username:password@host:port).
Proxy-Authorization: Basic base64("username:password")The contract:
- Scheme —
http://on the proxy endpoint itself, on every port. HTTPS target URLs are tunneled through it withCONNECT(your client does this automatically); you do not need anhttps://proxy URL. - No credentials (missing
Proxy-Authorizationheader) →407 Proxy Authentication Requiredwith aProxy-Authenticate: Basic realm="proxy"challenge. This is the standard proxy handshake: clients that wait to be challenged — and browsers configured to use a proxy — send their credentials on the retry. - Wrong or malformed credentials (bad password, unknown user, bad encoding)
→
401, with no challenge header. This is a deliberate fail-fast: the credential you sent is bad, so re-sending it won’t help. For privacy the gateway does not echo the username or say which half was wrong. - Both the plain-HTTP and the
CONNECT(HTTPS) paths authenticate before any connection to the target is opened, so a bad-credential HTTPS request fails at the tunnel handshake. - Your
Proxy-Authorizationheader is stripped before the request leaves the gateway — it never reaches the target.
Two distinct signals: a request with no credentials gets 407 + a
Proxy-Authenticate challenge — “authenticate and retry”. A request with
wrong or malformed credentials gets a bare 401 — “this credential is
bad, don’t retry it”. Most clients carry credentials in the proxy URL and send
them up front, so they never see the 407.
Geo-targeting
Append a 2-letter country code to your username with a hyphen. A bare username means the United States.
USERNAME → United States (default)
USERNAME-mx → Mexico
USERNAME-br → Brazil
USERNAME-ar → ArgentinaSupported countries: us, mx, br, ar (case-insensitive).
# Residential IP in Mexico
curl -x http://USERNAME-mx:PASSWORD@insightproxy.insightscrap.com:61000 \
https://api.ipify.orgRules worth knowing:
- Geo-targeting applies to residential and dynamic. The datacenter tier is a single US pool — a country suffix there is accepted but has no effect on the egress location.
- An unsupported 2-letter suffix (a code not in the list above) is rejected
with
401. This is deliberate: it surfaces a typo loudly instead of silently sending you out of the wrong country. - The country is parsed from the last hyphenated segment, and only when it’s
exactly two characters. A username that legitimately ends in a longer token
(e.g.
acme-prod) is left intact and defaults tous.
Sticky sessions
By default the gateway rotates: each new connection is assigned a fresh session, so you get a new IP. To hold one IP across many requests, add a session token to the username:
USERNAME-session-<token> → sticky IP
USERNAME-session-<token>-mx → sticky IP, in Mexico- The token is yours to choose — letters, digits and underscore, up to 64 characters. The same token returns the same exit IP; a different token gets a different IP. Rotate the token whenever you want a fresh IP; keep it to stay put.
- Tiers. Sticky sessions are supported on all three tiers. The residential tier holds a stable IP for the session’s lifetime and is the tier to use when you need a guaranteed pinned IP. The datacenter tier pins one IP per session token. On the dynamic tier a session keeps you on one IP too, but because that tier rotates across a large pool, treat long-run IP stability as best-effort.
- Order matters in the username, but the gateway handles it for you: the
-session-<token>segment comes first, the-<country>suffix last. Soalice-session-checkout1-mxis useralice, sessioncheckout1, countrymx.
import requests
user = "USERNAME"
pw = "PASSWORD"
def proxy(port, *, session=None, country=None):
u = user
if session:
u += f"-session-{session}"
if country:
u += f"-{country}"
return {"http": f"http://{u}:{pw}@insightproxy.insightscrap.com:{port}",
"https": f"http://{u}:{pw}@insightproxy.insightscrap.com:{port}"}
# Pin one residential IP in the US for a multi-step flow (login → cart → checkout)
s = requests.Session()
s.proxies.update(proxy(61000, session="checkout1"))
s.get("https://example.com/login")
s.get("https://example.com/cart") # same exit IP as the line aboveA sticky token binds to its first country. A session token pins one exit
IP, and that IP’s country is fixed the first time the token is used. Reusing
the same token under a different country returns the country it was
originally pinned to — not the new one. Give each country its own token: rather
than reuse checkout1 with both -mx and -br, use distinct tokens like
mxcheckout1 (with -mx) and brcheckout1 (with -br).
When to go sticky vs. rotate. Use a sticky session when a target ties a multi-request flow to one IP (logins, carts, pagination behind a session cookie). Use the default rotation — or a fresh token per request — for broad crawling where you want to spread load across many IPs.
Keep-alive pins an IP. A single open CONNECT tunnel (one kept-alive HTTPS
connection through the proxy) rides the same exit IP for its whole lifetime,
regardless of rotation. If you pool connections and want a new IP on every
request, either disable HTTP keep-alive or give each request a unique
-session-<token>.
Username reference
Everything you can express lives in the username. The full layout is:
<username>[-session-<token>][-<country>]| Segment | Optional? | Example | Effect |
|---|---|---|---|
<username> | required | acme | Your credential. |
-session-<token> | optional | -session-checkout1 | Pin one exit IP; same token → same IP. Token is letters/digits/underscore, up to 64 chars. Omit to rotate. |
-<country> | optional | -mx | Egress country (us/mx/br/ar). Omit for us. |
The password is always your credential’s password, unchanged — all of the targeting is in the username.
Using it from your stack
The gateway is a standard HTTP proxy, so integration is whatever your tool’s normal proxy configuration is. A few common ones:
curl
curl -x http://USERNAME-br:PASSWORD@insightproxy.insightscrap.com:61000 \
https://example.comPython — requests
import requests
proxies = {
"http": "http://USERNAME:PASSWORD@insightproxy.insightscrap.com:60000",
"https": "http://USERNAME:PASSWORD@insightproxy.insightscrap.com:60000",
}
r = requests.get("https://example.com", proxies=proxies)Python — Scrapy
Set the proxy per request via request.meta["proxy"] and add the auth header,
or point http_proxy / https_proxy at the gateway. Per-request is the common
pattern because it lets you vary tier (port) and country (username) request by
request:
import base64
class InsightProxyMiddleware:
HOST = "insightproxy.insightscrap.com"
PORTS = {"datacenter": 60000, "residential": 61000, "dynamic": 62000}
def __init__(self, user, password):
self.user, self.password = user, password
def process_request(self, request, spider):
tier = request.meta.get("proxy_type", "datacenter")
country = request.meta.get("proxy_country") # e.g. "mx"
session = request.meta.get("proxy_session") # sticky token, optional
user = self.user
if session:
user += f"-session-{session}"
if country:
user += f"-{country}"
request.meta["proxy"] = f"http://{self.HOST}:{self.PORTS[tier]}"
token = base64.b64encode(f"{user}:{self.password}".encode()).decode()
request.headers["Proxy-Authorization"] = f"Basic {token}"Node — fetch / undici
import { ProxyAgent, fetch } from "undici";
const agent = new ProxyAgent(
"http://USERNAME-mx:PASSWORD@insightproxy.insightscrap.com:61000"
);
const res = await fetch("https://example.com", { dispatcher: agent });Go
proxyURL, _ := url.Parse("http://USERNAME:PASSWORD@insightproxy.insightscrap.com:60000")
client := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}}
resp, _ := client.Get("https://example.com")Store the username, password, host and ports as environment variables rather than hard-coding them, and read them at runtime. Rotating a leaked password in the dashboard then only means updating one secret.
The dynamic tier in detail
The dynamic tier (port 62000) fetches the target for you, rather than
opening a pass-through tunnel: the gateway receives your request, retrieves the
target from its large rotating IP pool, and streams the response back. That
difference has a few practical consequences:
- No
CONNECTtunneling. The gateway performs the HTTPS request for you, so you send an ordinary proxied HTTP request; the target is fetched over HTTPS by default. (Most clients handle this transparently.) - Request body cap of 10 MB. A larger body returns
413. - Widest, most volatile IP surface — good for high-volume crawling where per-request IP diversity matters more than holding a session. Sticky tokens still pin an IP when you need them.
For the datacenter and residential tiers, HTTPS works the usual way — your client
opens a CONNECT tunnel and the gateway relays the bytes.
Rate limits
Each credential has a per-tier request rate limit, default 100 requests/minute, adjustable per tier in the dashboard.
- Over the limit →
429 Too Many Requestswith aRetry-After: <seconds>header. Honor it — back off for that many seconds and retry. - Limits are counted per credential, per tier, so datacenter and residential traffic on the same credential don’t share a bucket.
Error reference
The gateway is careful to tell you whose fault a failure is — it does not
mask every problem as one generic error. Distinguish two families: access
errors (4xx, about your request or account) and network errors (5xx,
about the target or the gateway).
| Status | Meaning | What to do |
|---|---|---|
401 | Wrong or malformed credentials, or an unsupported country suffix. | Fix the credential or the username suffix. Not retryable as-is. |
402 | Spend cap reached or token balance exhausted (X-Token-Denied / X-Risk-Denied header carries the reason). | Stop; raise the cap or top up. |
403 | Tier not enabled for this credential, or org risk controls paused traffic (X-Risk-Denied). | Enable the tier, or resolve the risk hold. |
407 | No credentials were sent — a proxy-auth challenge, with Proxy-Authenticate. | Send Proxy-Authorization and retry (most clients do this automatically). |
429 | Rate limit or bandwidth cap exceeded. | Back off per Retry-After, then retry. |
502 | Target unreachable or blocked (DNS failure, target refused/blocked the fetch). | Retry, ideally on another IP (rotate the session token) or a higher tier. |
503 | The proxy network is temporarily unavailable or rate-limited. | Retry with backoff. |
504 | Target connect timeout. | Retry; consider a different tier/country. |
On a 5xx failure the response also carries an X-Insightscrap-Error header
with a short slug (e.g. target_dns_failed, target_timeout, rate_limited).
Log it — it makes “why did this request fail” answerable at a glance.
A sensible retry policy: retry 429 after Retry-After; retry 502/503/504
a few times with exponential backoff, rotating the session token so the retry
lands on a different IP; treat 401/402/403 as non-retryable and surface
them.
What gets metered
Every request is metered and rolls up into your organization’s analytics under a
per-tier service key — datacenter, residential, or dynamic. For each
request the platform records the target host, request count, error count,
bytes sent and received (split), latency, and egress country, so you can
see spend and volume broken down by tier, host and geo in the dashboard.
Proxy traffic that originates from a managed browser is metered under a
separate browser_<tier> key (e.g. browser_datacenter) so you can tell raw
proxy usage apart from browser egress at a glance — even though both bill at
the same tier rate. See Managed Browsers.
Connection notes
- Timeouts. Idle
CONNECTtunnels are held open for up to 5 minutes; outbound requests to the target use a 30-second timeout. Keep long-lived tunnels active if you need them beyond that. - Response headers. Hop-by-hop headers and internal infrastructure headers
are stripped from responses.
Set-Cookieis passed through to you. - WebSockets work over the
CONNECTpath (datacenter and residential tiers), bounded by the tunnel idle timeout. The dynamic tier does not tunnel, so it can’t carry WebSocket traffic. - Concurrency. There is no fixed cap on concurrent connections at the proxy; the practical ceiling is your per-tier rate limit.
Rules
- Pick the tier with the port, the country and session with the username —
never a custom header. The gateway only reads standard
Proxy-Authorization. - Never ship credentials in code. Read them from the environment so a rotation is a one-line secret change.
- Honor
Retry-Afteron429, and rotate the session token when retrying a5xxso you don’t hammer the same bad IP.