Requests reads proxies from a plain dict passed to any request method. One dict covers every protocol:
import requests
proxies = {
"http": "http://USER:PASS@GATEWAY:PORT",
"https": "http://USER:PASS@GATEWAY:PORT",
}
r = requests.get("https://api.ipify.org", proxies=proxies, timeout=15)
print(r.text) # your proxy's exit IP
"https" key does not require an HTTPS proxy — it means "use this proxy for https:// targets". A plain http:// proxy entry handles HTTPS targets via CONNECT, exactly like cURL.SOCKS5
SOCKS5 needs the socks extra (pulls in PySocks):
pip install "requests[socks]"
proxies = {
"http": "socks5h://USER:PASS@GATEWAY:PORT",
"https": "socks5h://USER:PASS@GATEWAY:PORT",
}
As with cURL, prefer socks5h:// — DNS resolves on the proxy side, eliminating DNS leaks.
Sessions: reuse connections and credentials
For anything beyond a one-off call, use a Session. It pools TCP connections (much faster through a remote gateway) and lets you set the proxy once:
import requests
s = requests.Session()
s.proxies = {"http": "http://USER:PASS@GATEWAY:PORT",
"https": "http://USER:PASS@GATEWAY:PORT"}
s.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"})
r = s.get("https://target-site.com", timeout=(5, 20)) # (connect, read)
Timeouts and retries that survive production
Proxies add latency and occasionally stall. Always set both connect and read timeouts, and retry idempotent GETs:
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
retry = Retry(total=3, backoff_factor=1.5,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "HEAD"])
s.mount("https://", HTTPAdapter(max_retries=retry, pool_maxsize=20))
Rotation patterns
With a rotating gateway, rotation happens server-side — you get a fresh exit IP per request (or per session token):
# new IP per request (gateway rotates)
for page in pages:
s.get(page, proxies=proxies, timeout=15)
# sticky session: same IP for a burst, then rotate
sticky = proxies.copy()
sticky["http"] = sticky["http"].replace("USER", "USER-session-7f3a")
sticky["https"] = sticky["https"].replace("USER", "USER-session-7f3a")
Debugging checklist
ProxyError / 407— credentials wrong; URL-encode special chars (%40for@)SSLErroronly via proxy — don't disable verification; switch to socks5h:// or a TLS proxy entryConnectTimeout— connect timeout too small for the gateway's region; usetimeout=(5, 20)- Sudden IP drops mid-run — expected with residential pools; your retry adapter should absorb it
- Target shows datacenter ASN — you are hitting a datacenter pool, switch to residential
FAQ
Does the https key in proxies need an HTTPS proxy?
No. The key is the target scheme, not the proxy protocol. A plain http:// proxy entry handles https:// targets via CONNECT tunneling.
How do I use SOCKS5 with Requests?
Install the extra with pip install requests[socks], then use socks5h:// in your proxies dict. socks5h resolves DNS on the proxy side, avoiding DNS leaks.
Requests vs httpx for proxies?
Both support the same proxies dict format. httpx additionally supports HTTP/2; Requests has a larger ecosystem. The proxy concepts in this guide apply to both.
How do I verify my proxy actually rotates?
Send 50 requests through one gateway entry and count unique exit IPs. IPLight publishes its measured pool depth openly in the live pool report.
IPLight's rotating residential pool: 215,000+ live IPs, 170+ countries, from $1.20/GB — see pricing or verify the pool in the live pool report.