Configure a Rotating Residential Proxy with cURL, Python, and Node.js
Practical, provider-agnostic setup examples for cURL, Python, and Node.js — with environment-based credentials, timeouts, error handling, and authorized targets throughout.
Once you have chosen a provider, configuring a rotating residential proxy is straightforward in most environments. The patterns below cover cURL, Python, and Node.js, and they share the same good habits throughout: credentials come from environment variables, every request has a timeout, errors are handled explicitly, requests are paced considerately, and the target is always an authorized one such as example.com. Replace the placeholder gateway and credentials with your provider's real values from their documentation.
Before you start
Set your credentials as environment variables so they never appear in your code or version control. Create a git-ignored .env and a committed .env.example that lists only the variable names. You will also need your provider's gateway host and port, and any parameter syntax they use for country targeting or sticky sessions — these vary, so keep their docs open.
# .env (git-ignored)
PROXY_USER=your_username_here
PROXY_PASS=your_password_here
PROXY_GATEWAY=gateway.example-provider.net:7000
cURL
cURL is the quickest way to confirm a proxy works. This sends a single request through the rotating gateway with a timeout:
source .env # or export the variables another way
curl --proxy "http://$PROXY_USER:$PROXY_PASS@$PROXY_GATEWAY" \
--max-time 30 \
https://example.com/
For per-request rotation, simply send multiple requests — each may use a different exit. To hold a sticky session, add your provider's session parameter (often embedded in the username). To target a country, add the provider's country parameter. Always confirm the exact syntax in their documentation:
# Sticky session (pattern varies by provider):
curl --proxy "http://$PROXY_USER-session-abc123:$PROXY_PASS@$PROXY_GATEWAY" \
--max-time 30 https://example.com/
# Country target (pattern varies by provider):
curl --proxy "http://$PROXY_USER-country-de:$PROXY_PASS@$PROXY_GATEWAY" \
--max-time 30 https://example.com/
Python
In Python, the requests library makes proxy use simple. This example reads credentials from the environment, sets a timeout, handles errors, and paces a small loop:
import os, time, requests
user = os.environ["PROXY_USER"]
pw = os.environ["PROXY_PASS"]
gw = os.environ["PROXY_GATEWAY"]
proxies = {
"http": f"http://{user}:{pw}@{gw}",
"https": f"http://{user}:{pw}@{gw}",
}
TARGET = "https://example.com/" # authorized target only
for i in range(5): # small, paced sample
try:
r = requests.get(TARGET, proxies=proxies, timeout=30)
print(i, r.status_code, len(r.content))
except requests.RequestException as e:
print(i, "error:", e) # explicit handling; don't print creds
time.sleep(1) # considerate pacing
For sticky sessions, build the username with your provider's session parameter and keep it constant across the requests that belong to one flow; roll it for the next flow. For retries, wrap the request in a small retry helper with a capped number of attempts and a backoff delay, so a transient failure does not immediately abort your task.
Node.js
In Node.js, a common approach uses a proxy agent with the built-in fetch or a HTTP client. This example uses undici's ProxyAgent pattern with environment credentials, a timeout via an AbortController, and error handling:
import { ProxyAgent } from "undici";
const { PROXY_USER, PROXY_PASS, PROXY_GATEWAY } = process.env;
const dispatcher = new ProxyAgent(
`http://${PROXY_USER}:${PROXY_PASS}@${PROXY_GATEWAY}`
);
const TARGET = "https://example.com/"; // authorized target only
async function fetchOnce(i) {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 30000); // 30s timeout
try {
const res = await fetch(TARGET, { dispatcher, signal: ctrl.signal });
const body = await res.text();
console.log(i, res.status, body.length);
} catch (err) {
console.log(i, "error:", err.message); // no creds in logs
} finally {
clearTimeout(t);
}
}
for (let i = 0; i < 5; i++) {
await fetchOnce(i);
await new Promise((r) => setTimeout(r, 1000)); // considerate pacing
}
As with Python, express sticky sessions and targeting through your provider's parameter syntax, keep credentials in the environment, and never log the full proxy URL.
Good habits that apply everywhere
- Environment-based credentials. Never hard-code secrets; keep them out of source control and logs.
- Timeouts on every request. A slow exit should fail fast, not hang your task.
- Explicit error handling. Catch failures, log them without exposing credentials, and decide whether to retry.
- Considerate pacing. Add a delay between requests and cap concurrency so your task behaves responsibly.
- Bounded retries. Retry transient failures a limited number of times with backoff; do not retry forever.
- Authorized targets. Test and run only against sites you own or are permitted to access.
Verifying your setup
After configuring, confirm two things on an authorized endpoint that echoes request details: first, that your requests are actually exiting through the proxy rather than your own address; and second, that any targeting you set is taking effect. Building this verification into your setup catches misconfiguration early, before you rely on data that may have been collected from the wrong vantage point.
Troubleshooting quick reference
If requests fail immediately, check credentials and gateway host/port. If they hang, confirm your timeout is set and the gateway is reachable. If targeting seems ignored, re-read the provider's parameter syntax — a small formatting difference is a common cause. If success is intermittent, that may reflect residential variability rather than a configuration error; measure it before assuming the setup is broken. Our troubleshooting guide covers these in depth.
From first request to production
Getting a single request working is the easy part; hardening it for production is where the real work lies. Before you scale, wrap your requests in a small client that centralises credentials, timeouts, retries with backoff, and logging that never prints secrets. Add the verification step so you know traffic is exiting through the proxy and that targeting is taking effect. Build in considerate pacing and a cap on concurrency. Only once this scaffolding is in place should you increase volume. Taking the time to build a disciplined client early prevents a class of production problems later, and it means that when something does go wrong, you have consistent logging and error handling to diagnose it quickly rather than a pile of ad-hoc scripts.
Summary
Configuring a rotating residential proxy in cURL, Python, or Node.js follows the same shape: point at the provider's gateway with environment-based credentials, add targeting or session parameters per their documentation, and wrap every request with timeouts, error handling, and considerate pacing against authorized targets. Verify that traffic exits through the proxy and that targeting works before scaling. These habits keep your setup secure, reliable, and responsible. For credential security specifically, see the authentication guide.
Responsible-use reminder
This guide is general information for lawful, authorized use only — not legal advice. Always respect the terms of the sites you interact with and the laws that apply to you, and seek qualified legal guidance for anything consequential.