Integration4 min read

Configure a proxy in Python Requests

Make a Python Requests proxy configuration explicit, encode credentials correctly, and distinguish connect and read timeouts from a total job deadline.

On this page

The starting point

A small, explicit Requests configuration makes proxy selection and authentication easier to reproduce across development and production.

Prepare an explicit configuration

Install Requests with python -m pip install requests in your project's virtual environment. Inject PROXY_USERNAME and PROXY_PASSWORD privately. Set PROXY_URL to the provider's gateway, including its scheme and port; https://proxy.example.invalid:8443 is only a nonworking illustration.

The dictionary keys below select the destination scheme. Both keys may point at the same gateway. Pass the dictionary on the request instead of relying on a workstation's inherited proxy settings.

Encode credentials and bound network waits

Save as proxy_check.py and run python proxy_check.py. Encode the username and password individually so characters such as @ or / cannot change the URL structure. Keep the original proxy URL free of credentials.

proxy_check.py · Python 3 + Requests
import os
from urllib.parse import quote, urlsplit, urlunsplit
import requests

gateway = urlsplit(os.environ["PROXY_URL"])
if gateway.scheme not in {"http", "https"} or not gateway.hostname:
    raise ValueError("Use your provider's HTTP(S) proxy URL")
if gateway.username is not None or gateway.path not in {"", "/"} or gateway.query or gateway.fragment:
    raise ValueError("Keep credentials and paths out of PROXY_URL")
username = quote(os.environ["PROXY_USERNAME"], safe="")
password = quote(os.environ["PROXY_PASSWORD"], safe="")
proxy = urlunsplit((gateway.scheme, f"{username}:{password}@{gateway.netloc}", "", "", ""))

with requests.Session() as session:
    session.trust_env = False
    with session.get(
        "https://example.com/",
        proxies={"http": proxy, "https": proxy},
        timeout=(10, 20),
        allow_redirects=False,
        stream=True,
    ) as response:
        response.raise_for_status()
        print({"status": response.status_code})

Know what the timeout measures

The tuple supplies separate connect and read timeouts. A read timeout limits waiting for socket data; it is not a total download deadline. Apply a separate wall-clock budget in your job runner when a whole task must finish by a fixed time. This diagnostic streams and closes the response without downloading the full body.

Setting trust_env to False also disables Requests' environment-derived authentication and CA-bundle settings. If your organization uses a custom trust bundle, pass its approved file explicitly with verify. Do not use verify=False to make a failing test pass.

Make failures comparable

Run the same gateway and destination in curl before adding retry logic. Record exception class, attempt number and elapsed time, with credentials removed. A reproducible authentication error needs a configuration change; repeating it at higher concurrency adds noise.

  • SOCKS is optional: install requests[socks] and use the matching SOCKS URL in a separate configuration.
  • For SOCKS, socks5h delegates destination DNS to the proxy; socks5 resolves locally.
  • A successful HTTP request alone does not verify the exit's location.

From reading to doing

Before you ship

  • Use a project virtual environment.
  • Encode credentials separately from the gateway.
  • Keep a job deadline in addition to network timeouts.

Sources & further reading

Technical references used for this guide. Check the documentation for your installed version and your provider’s supported configuration.