# How to Use a Proxy with Python Requests

> Use a proxy with Python requests: the proxies dict, HTTP/HTTPS/SOCKS5, authentication, session reuse, rotation for scraping, and the common mistakes that break it.

[Home](https://quanticdata.io/)/[Blog](https://quanticdata.io/blog/)/How to Use a Proxy with Python Requests

# How to use a proxy with Python requests: syntax, auth, rotation and pitfalls

GuidesJul 30, 2026·5 min read·QuanticData Team

On this page [The basic syntax](/blog/how-to-use-a-proxy-with-python-requests/#the-basic-syntax) [Authenticated proxies](/blog/how-to-use-a-proxy-with-python-requests/#authenticated-proxies) [SOCKS5 proxies](/blog/how-to-use-a-proxy-with-python-requests/#socks5-proxies) [Reuse and rotation for scraping](/blog/how-to-use-a-proxy-with-python-requests/#reuse-and-rotation-for-scraping) [The pitfalls that silently break it](/blog/how-to-use-a-proxy-with-python-requests/#the-pitfalls-that-silently-break-it) [Setting a timeout and handling proxy failures](/blog/how-to-use-a-proxy-with-python-requests/#setting-a-timeout-and-handling-proxy-failures) [When requests isn't enough](/blog/how-to-use-a-proxy-with-python-requests/#when-requests-isn-t-enough)

To use a proxy with Python requests, pass a `proxies` dictionary mapping the URL scheme to your proxy URL. That is the whole basic idea — one dict, applied per request or set once on a session. The details that trip people up are authentication, HTTPS coverage, SOCKS5 support and rotation, and they are the difference between a scraper that works and one that silently leaks your real IP.

## The basic syntax

The `proxies` dict keys are schemes (`http` and `https`), and the values are the proxy URL to use for each:

```
import requests

proxies = {
    "http":  "http://pr.quanticdata.io:7777",
    "https": "http://pr.quanticdata.io:7777",
}
r = requests.get("https://ipinfo.io/ip", proxies=proxies)
print(r.text)   # the proxy's exit IP, not yours
```

Note the values are the *same* proxy for both schemes here — the key is the scheme of the **target** URL, not the proxy. This is the number-one confusion: people set only `http`, then hit an `https://` site and wonder why the proxy is ignored. Almost every real target is HTTPS, so you almost always need the `https` key.

## Authenticated proxies

Paid proxies require credentials, which go inline in the proxy URL as `user:pass@host:port`:

```
proxy = "http://USER:PASS@pr.quanticdata.io:7777"
proxies = {"http": proxy, "https": proxy}
r = requests.get("https://example.com", proxies=proxies)
```

If your password contains special characters (`@`, `:`, `/`), URL-encode them with `urllib.parse.quote` or the credentials will be parsed wrong and you'll get a 407. This is the second most common failure after the HTTPS-key mistake.

## SOCKS5 proxies

For SOCKS5 (useful for non-HTTP traffic or stricter anonymity), install the extra and use the `socks5` scheme in the proxy URL:

```
pip install "requests[socks]"
```

```
proxy = "socks5://USER:PASS@host:1080"
proxies = {"http": proxy, "https": proxy}
```

Use `socks5h://` (with the `h`) to have the proxy resolve DNS, which prevents your machine's DNS lookups from leaking the domains you're visiting — worth it for anything privacy-sensitive.

## Reuse and rotation for scraping

For more than one request, use a `Session` so the proxy (and connection pooling) applies to every call without repeating yourself:

```
s = requests.Session()
s.proxies = proxies
for url in urls:
    r = s.get(url)   # all go through the proxy
```

Rotation is where scraping gets serious. If you point the session at a [rotating proxy endpoint](https://quanticdata.io/rotating-proxies/), the provider assigns a fresh IP per request automatically — no rotation logic in your code. That is far cleaner than maintaining and health-checking your own IP list, which is the DIY approach that eats afternoons. For defended targets use [residential IPs](https://quanticdata.io/residential-proxies/); for high-volume calls to tolerant targets, datacenter is cheaper. We cover the setup for rotating endpoints in [how to set up rotating proxies](https://quanticdata.io/blog/how-to-set-up-rotating-proxies/).

## The pitfalls that silently break it

| Symptom | Cause | Fix |
| --- | --- | --- |
| Proxy ignored on HTTPS sites | Only the `http` key set | Set the `https` key too |
| 407 Proxy Authentication Required | Special chars in password not encoded | URL-encode credentials |
| SSL errors through the proxy | Corporate/MITM proxy cert | Point `verify` at the CA bundle, not `False` |
| Env var overrides your dict | `HTTP_PROXY` set in the environment | Pass `trust_env=False` on the session, or unset it |
| DNS leaks with SOCKS | `socks5://` resolves locally | Use `socks5h://` |

Setting `verify=False` to make SSL errors go away is a common mistake — it disables certificate checking entirely and opens you to interception. Fix the actual cause (usually the proxy's CA) instead.

## Setting a timeout and handling proxy failures

One habit that separates a toy script from a working scraper: always set a timeout, and handle the proxy-specific errors. A dead or slow proxy will otherwise hang your request indefinitely, and at scale one bad exit IP shouldn't kill the whole run. Wrap each call so a proxy failure is caught, logged and retried rather than crashing the loop:

```
from requests.exceptions import ProxyError, ConnectTimeout

try:
    r = s.get(url, timeout=15)
    r.raise_for_status()
except (ProxyError, ConnectTimeout):
    # bad exit IP or slow proxy — retry (a rotating
    # endpoint hands you a different IP on the next call)
    r = s.get(url, timeout=15)
```

With a rotating endpoint this retry pattern is especially effective, because the retry automatically comes from a fresh IP — a transient block or a dead exit self-heals on the next attempt. Without a timeout, a single unresponsive proxy can stall a scrape for minutes; fifteen seconds is a sane default for most targets.

## When requests isn't enough

A proxy solves the IP problem, but `requests` only fetches raw HTML — it doesn't run JavaScript, so client-rendered content is invisible, and you still write your own parsing. When a target renders in the browser or blocks harder than proxies alone can beat, point `requests` at a [scraping API](https://quanticdata.io/web-scraping-api/) instead of the site directly: one POST with the URL, and you get back clean Markdown or structured JSON with the proxy, rendering and anti-block handled server-side. Your Python stays exactly this simple — `requests.post(api, json={"url": target})` — but the fragile parts move off your machine. Keep raw `requests`+proxy for simple static targets; reach for the API when the page fights back.

### Sources & further reading

- [Stack Overflow — Proxies with the Python 'requests' module](https://stackoverflow.com/questions/8287628/proxies-with-python-requests-module)

- [GeeksforGeeks — Proxies with Python requests module](https://www.geeksforgeeks.org/python/proxies-with-python-requests-module/)

## FAQ

Quick answers on how to proxy python requests.

[Something else? Ask us →](mailto:hello@quanticdata.io)

### Why is my proxy ignored in Python requests?

Almost always because you only set the http key in the proxies dict but the target is an https:// site. The dict keys are the scheme of the target URL, not the proxy — set both http and https keys to the same proxy. The second common cause is an HTTP_PROXY environment variable overriding your dict; pass trust_env=False to stop that.

### How do I use an authenticated proxy with requests?

Put the credentials inline in the proxy URL: http://user:pass@host:port, then use that string as both the http and https values. If the password contains special characters like @ or :, URL-encode them with urllib.parse.quote, or the URL is parsed wrong and you get a 407 Proxy Authentication Required.

### Does requests support SOCKS5 proxies?

Yes, after installing the extra: pip install 'requests[socks]'. Then use a socks5:// (or socks5h://) proxy URL in the proxies dict. Use socks5h:// so the proxy resolves DNS instead of your machine, which prevents leaking the domains you visit — important for privacy-sensitive scraping.

### How do I rotate proxies with Python requests?

The clean way is to point a requests.Session at a rotating proxy endpoint — the provider assigns a fresh IP per request automatically, with no rotation code on your side. Maintaining your own IP list and rotating manually works but means health-checking dead proxies yourself; a rotating endpoint removes that entire chore.

### Should I set verify=False to fix proxy SSL errors?

No — that disables certificate verification entirely and exposes you to interception. SSL errors through a proxy usually mean a corporate or MITM proxy with its own CA; point requests' verify parameter at that CA bundle instead. For a normal forward proxy you shouldn't see SSL errors at all if the setup is correct.

## Keep the Python simple, move the hard parts off your box

Point requests at the scraping API — clean Markdown or JSON back, with residential proxies, rendering and anti-block handled. Pay per success, $2 of free usage every month.

[Start free — $2/month included](https://app.quanticdata.io/register)[Explore Residential Proxies from $0.80/GB](https://quanticdata.io/residential-proxies/)

## Related reading

[Data for AI How to Feed Data to an LLM Context window, RAG, tool calls or fine-tuning — the four ways to give an LLM your data, how each works, when to pick it, and how to keep the source fresh. Read →](https://quanticdata.io/blog/how-to-feed-data-to-an-llm/) [Guides How to Use a Proxy in n8n Two ways to route n8n through a proxy — per-node in the HTTP Request node or globally with env vars — the gotchas that trip people up, and rotation for scraping. Read →](https://quanticdata.io/blog/how-to-use-a-proxy-in-n8n/) [Guides Playwright Stealth in Python Install playwright-stealth, understand which automation tells it patches, why sophisticated detectors still win, and the IP-plus-fingerprint combination that lasts. Read →](https://quanticdata.io/blog/playwright-stealth-in-python/)

---

Source: https://quanticdata.io/blog/how-to-use-a-proxy-with-python-requests/ · Site index for AI: https://quanticdata.io/llms.txt
