Skip to content

Guides · Connect and debug

Python Requests proxy setup

Configure an authenticated proxy in Python, verify it from the same process as your job, and separate proxy failures from destination errors. The examples cover HTTP, SOCKS5, timeouts and reusable sessions without putting credentials in source code.

Short answers

How do I use a proxy with Python Requests?

Pass a proxies dictionary with http and https keys to the request. Each value is a complete proxy URL. The key describes the destination URL; the value describes how Python connects to the gateway.

Why is the HTTPS proxy value an http:// URL?

An HTTPS destination can travel through an HTTP proxy using CONNECT. Keep http:// for the HTTP gateway on 7000; Requests still verifies the destination’s HTTPS certificate.

How do I put a proxy password into a URL?

Read the username and password from your runtime configuration, then encode each once with urllib.parse.quote(value, safe=""). Do not encode a full URL or encode credentials that are already URL-encoded.

Does a Requests Session keep the proxy IP?

No. A Python Session manages cookies and connections. Gateway rotation is configured separately in the proxy username. A sticky gateway session keeps the same device while available; its IP can still change.

Working without Requests? The Python urllib guide uses the standard library, with an explicit opener and a prompted proxy password. Its handler settings are separate from the Requests session below.

Using an async client? Follow the separate HTTPX proxy setup guide for AsyncClient or the aiohttp proxy guide for ClientSession; their proxy arguments differ from Requests.

For a Scrapy project, configure the crawler itself using the Scrapy proxy guide. Settings on a separate Requests session do not configure Scrapy’s downloader.

Prepare the interpreter and connection

Start in the Python environment your application actually uses. Install Requests with that interpreter, then run the check there: a package installed on your laptop does not configure a container or a notebook kernel.

Install in your project environmentsh
python -m pip install requests
python -c "import requests; print(requests.__version__)"
  1. Open the connection builder, choose a pool and a country from the current availability, and select HTTP.
  2. Provide PROXY_USER as the complete generated username, including its pool, country and rotation settings. An account username alone is not a finished connection.
  3. Provide PROXY_PASSWORD as the proxy password. Your website password and API key are different credentials.
  4. Inject these values through your local runtime or deployment secret configuration. Keep them out of source control, command output and shared notebooks.

The setup reference explains the connection fields. If you already have a passing shell check, keep those same fields for this first Python request; changing the country and the client together makes a failure harder to isolate.

Make one authenticated HTTP proxy request

Save this as proxy_check.py. It requires the two credential variables and accepts an optional PROXY_SERVER containing only the scheme, host and port. The echo endpoint reports the address it observed; it does not prove that every destination will accept your traffic.

proxy_check.pypython
import os
from urllib.parse import quote

import requests

server = os.environ.get("PROXY_SERVER", "http://gw.portproof.org:7000")
if not server.startswith("http://") or "@" in server:
    raise SystemExit("Use an HTTP server address without credentials")

user = quote(os.environ["PROXY_USER"], safe="")
password = quote(os.environ["PROXY_PASSWORD"], safe="")
proxy = f"http://{user}:{password}@{server.removeprefix('http://')}"
proxies = {"http": proxy, "https": proxy}

try:
    with requests.Session() as session:
        session.trust_env = False
        session.verify = os.environ.get("REQUESTS_CA_BUNDLE") or True
        response = session.get(
            "https://api.portproof.org/v1/echo-ip",
            proxies=proxies,
            timeout=(10, 30),
        )
        response.raise_for_status()
        payload = response.json()
        if not isinstance(payload.get("ip"), str):
            raise ValueError("The endpoint did not return an IP address")
        print("HTTP", response.status_code, "exit", payload["ip"])
except requests.RequestException as error:
    raise SystemExit(f"Request failed: {type(error).__name__}") from None

Run python proxy_check.py. A successful result gives the HTTP status and your own observed exit address. The script deliberately avoids printing the proxy URL or raw exception text, either of which can end up in a shared job log.

The proxy dictionary follows the Requests proxy interface. Encoding only the credential components follows Python’s URL quoting reference; a slash in a password must be encoded too, which is why safe is empty.

Make the running process predictable

This check uses explicit per-request settings and turns trust_env off. It therefore does not inherit proxy choices or default authentication from the machine. It also opts back into a configured certificate bundle with session.verify; otherwise the normal trusted certificates remain enabled. See the Session interface.

If your organisation manages outbound networking centrally, keep that policy instead of copying the override blindly. Choose one configuration source, document it, and test from the deployed process. Check only whether required variables are present; do not dump the environment into a log. The curl works but the app does not guide covers process and container differences.

Check which proxy Requests actually used

Setting Session.proxies does not always make that proxy the route. We checked two local authenticated proxies and a local destination with Python 3.12.14, Requests 2.34.2 and urllib3 2.8.0 on 30 September 2026. These were real requests with synthetic credentials, not calls to a live proxy pool. Redirects were disabled for each check.

Routes recorded in the local Requests fixture
ConfigurationRoute recorded by the fixture
Environment proxy plus a different Session.proxies valueEnvironment proxy
Environment proxy plus proxies passed to get()Per-request proxy
trust_env=False with Session.proxies configuredSession proxy
Environment proxy and matching NO_PROXY, without explicit settingsDirect to the local destination
Matching NO_PROXY with a session or per-request proxyExplicit proxy still used

NO_PROXY did not remove the explicit proxy settings in these checks. If your job needs selected destinations to connect directly, implement that choice in the application and verify both routes. Do not assume an environment exclusion cancels every proxy setting. The Requests proxy configuration guide documents environment precedence. For differences between a shell and a worker, use the curl and app routing checklist.

The HTTPS checks also confirmed the certificate-bundle line in the example above: with trust_env=False, setting REQUESTS_CA_BUNDLE alone produced SSLError; assigning that bundle to session.verify succeeded with TLS verification enabled. The Session interface explains the environment setting.

These checks describe first-request behaviour in the named versions, with loopback HTTP proxies and redirects disabled. They do not establish redirect routing, SOCKS behaviour, TLS connections to a proxy, or live gateway availability and performance.

Use separate connection and reading limits

The tuple (10, 30) sets connection and read timeouts in seconds. These are example limits, not a promise about network speed. A read timeout limits how long the client waits without receiving data; it is not a thirty-second deadline for an entire download. Requests documents this distinction in its timeout guide.

Give a scheduled job a separate overall deadline and cap its work queue. A worker that keeps receiving small chunks can otherwise remain busy much longer than the read timeout suggests. Start with one small request before adding parallelism, retries or large response bodies.

Keep TLS certificate verification enabled. An HTTPS certificate failure needs a correct destination hostname and a trusted certificate chain; disabling verification does not repair proxy authentication.

Use SOCKS5 when your application needs it

Install the optional SOCKS supportsh
python -m pip install "requests[socks]"

For SOCKS5, keep the encoded user and password variables from the HTTP example and replace the proxy construction and dictionary with the following lines. Remove the HTTP-only server validation too. Both dictionary entries still follow the destination scheme.

Replacement SOCKS5 proxy settingspython
proxy = f"socks5h://{user}:{password}@gw.portproof.org:7001"
proxies = {"http": proxy, "https": proxy}

Requests uses socks5h for hostname resolution at the proxy; plain socks5 resolves the destination on the client. Pick the DNS location deliberately, then repeat the same echo check. The protocol comparison helps when an application supports both.

Separate Python sessions from gateway sessions

Reuse a Python Session for a related sequence of requests and close it when that unit of work ends. Keep its cookies separate from unrelated jobs. For a multi-step workflow, select a named sticky session in the connection builder and reuse that exact generated username throughout the workflow.

A new Python request is not necessarily a new network connection: connection reuse can keep an existing tunnel alive. Do not test connection-based rotation by demanding a different address after every session.get. Likewise, a repeated address alone cannot prove that routing is wrong. Read rotation and sticky sessions before turning either assumption into a test assertion.

Identify the failed stage before retrying

Python proxy failure checks
SymptomFirst check
ProxyError or a tunnel authentication failureThrough the HTTP gateway, a refused port, an unresolved gateway hostname, a connection timeout and a rejected CONNECT all raise ProxyError. Compare the full username, current proxy password, scheme and port with a fresh builder result. Use the 407 guide if authentication is refused.
ConnectionError with socks5hA refused SOCKS5 port or rejected SOCKS5 credentials. Check the port 7001, the complete username and the password.
InvalidSchema or missing SOCKS supportInstall requests[socks] in the same environment that runs the script.
ConnectTimeoutWith socks5h, the gateway connection or SOCKS5 greeting did not finish in time; the HTTP gateway reports that stage as ProxyError. Check reachability of the gateway host and port from the actual worker.
ReadTimeoutNo data arrived within a limit. Through the HTTP gateway this also happened when the gateway accepted the connection and never answered CONNECT. Test the small echo endpoint before the application destination; limit subsequent retries.
SSLErrorCheck hostname, system time and the certificate bundle. Preserve verification.
A response with status 403 or 429Establish whether the response came from the gateway or destination. Respect destination access rules and rate limits.
A JSON decoding errorThe request returned a body that was not the expected JSON. Check the status and content type without logging credentials.

We recorded the ProxyError, ConnectionError, ConnectTimeout, ReadTimeout and SSLError cases above with Requests 2.34.2, urllib3 2.8.0 and PySocks 1.7.1 against local proxies on 1 October 2026. If the gateway is not reached at all, follow connection refused and timeouts.

Correct rejected credentials before retrying. Start with 407 authentication troubleshooting or CONNECT tunnel failures. For permitted reads that fail transiently, bound the number of retries and include a delay. Do not automatically replay purchases, submissions or other operations with side effects.

Once the echo check passes, replace it with one authorised application request and check the response your job actually needs. Measure a representative run before choosing how many GB to buy. See how traffic is counted and current per-GB prices.

What is not allowed

Use these examples for authorised QA, price monitoring, ad verification and research that respects the destination’s terms and access rules. A working proxy does not grant permission to collect data or send requests. See the acceptable-use policy.

Python Requests proxy setup · Portproof