# Python Requests 代理配置：认证与 SOCKS5

Source: https://ipvolt.com/zh/guides/python-requests-proxy
Markdown: https://ipvolt.com/zh/guides/python-requests-proxy.md
Language: zh-CN

[ipvolt 首页](https://ipvolt.com/zh.md) / [指南](https://ipvolt.com/zh/guides.md) / Python Requests 代理配置：认证与 SOCKS5

集成
审校于: 2026-09-17
阅读约 7 分钟
作者： ipvolt

在 Python Requests 中配置代理：proxies 字典、Session 默认值、凭据、通过 requests[socks] 使用 SOCKS5、环境变量与 ProxyError。

## 起点

proxies 字典、Session 级默认值、凭据编码、SOCKS5、环境变量行为，以及代理步骤失败时 Requests 抛出的异常。

## 用 proxies 字典为请求设置代理

Requests 从一个以目标协议为键的字典中选择代理。https 键的值用于 https:// 目标，http 键的值用于 http:// 目标；两者通常指向同一个网关。all 键适用于任何协议，而 https://example.com 这样的键则把某一个主机固定到特定网关。

值是代理 URL，带有它自己的协议。http://host:port 是普通 HTTP 代理；对于 https:// 目标，Requests 会请求它打开一条 CONNECT 隧道。只有当提供商在代理上终止 TLS 时，才把 https://host:port 用作代理 URL。始终传入 timeout；否则一个停滞的代理会无限期阻塞调用。

### requests.get 与 proxies · 单个请求

```python
import requests

PROXIES = {
    "http": "http://proxy.example.invalid:8080",
    "https": "http://proxy.example.invalid:8080",
}

response = requests.get(
    "https://example.com/",
    proxies=PROXIES,
    timeout=(10, 20),
)
print(response.status_code)
```

## 使用 Session 让每个请求共享代理

Session 把连接池、Cookie 和代理设置放在一起。设置一次 session.proxies，通过该 Session 发出的每个请求都会使用这个网关，而单次调用上的 proxies 参数仍然可以覆盖它。也是在这里决定进程环境是否可以参与配置：trust_env=False 会阻止 Requests 读取 HTTP_PROXY、HTTPS_PROXY、NO_PROXY、netrc 凭据和 REQUESTS_CA_BUNDLE 变量，从而只由代码决定路由。

### requests.Session · 共享的代理设置

```python
import requests

with requests.Session() as session:
    session.trust_env = False
    session.proxies.update({
        "http": "http://proxy.example.invalid:8080",
        "https": "http://proxy.example.invalid:8080",
    })
    for url in ("https://example.com/", "https://example.com/robots.txt"):
        response = session.get(url, timeout=(10, 20))
        print(url, response.status_code)
```

## 代理认证：把凭据编码进 URL

Requests 从代理 URL 本身发送代理凭据，形如 http://username:password@host:port；它会替你添加 Proxy-Authorization 请求头。auth 参数属于目标站点认证，不会到达代理。

分别对用户名和密码进行编码，使 @、: 或 / 这类字符无法改变 URL 结构，并让原始 PROXY_URL 不包含凭据。把下面的脚本保存为 proxy_check.py，在虚拟环境中用 python -m pip install requests 安装 Requests 之后，运行 python proxy_check.py。https://proxy.example.invalid:8443 只是一个无法工作的示例。

### proxy_check.py · Python 3 + Requests

```python
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})
```

## 环境变量与 trust_env

当 trust_env 保持默认值 True 时，Requests 会通过 urllib.request.getproxies() 从环境中补齐你未设置的协议。它接受大写或小写的 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 和 NO_PROXY，在 macOS 上还会读取系统代理配置。这在工作站上很方便，但在容器中却是常见的意外来源：从镜像继承的 HTTPS_PROXY 会把你以为是直连的流量转走。

NO_PROXY 是以逗号分隔的主机名、域名后缀或 IP 地址列表，其中的条目绕过代理。对于路由必须可复现的任务，设置 trust_env=False 并显式传入 proxies；对于工作站脚本，设置变量并在调用 Requests 时不带 proxies 参数就足够了。

### HTTPS_PROXY · trust_env 为 True 时自动读取

```sh
export HTTPS_PROXY='http://proxy.example.invalid:8080'
export NO_PROXY='localhost,127.0.0.1,.internal.example'
python -c 'import requests; print(requests.get("https://example.com/", timeout=(10, 20)).status_code)'
```

## SOCKS5 代理：requests[socks]，socks5 与 socks5h 的区别

SOCKS 支持来自 PySocks 附加依赖：用 python -m pip install "requests[socks]" 安装，然后在同一个字典中使用 socks5:// 或 socks5h:// 代理 URL。socks5 在本地解析目标主机名并向代理发送 IP 地址；socks5h 发送主机名由代理解析，这通常是远程网关所期望的。用户名和密码放在 URL 中，方式与 HTTP 代理完全相同。

### socks5h 代理 · requests[socks]

```python
import requests

PROXIES = {
    "http": "socks5h://proxy.example.invalid:1080",
    "https": "socks5h://proxy.example.invalid:1080",
}
response = requests.get("https://example.com/", proxies=PROXIES, timeout=(10, 20))
print(response.status_code)
```

## 在多个代理之间轮换

当任务需要把请求分散到多个网关时，保留一个 Session 用于连接池，并按请求选择 proxies 参数。示例循环遍历一个列表；真实任务会从配置中取值，记录每个请求由哪个网关服务，并在网关反复失败后将其下线而不是立即重试。连续请求是否应保持同一个出口地址是会话模型层面的决定，许多提供商通过用户名或专用端口来表达它。请遵循提供商的文档，而不是从一次成功的请求中推断。

### itertools.cycle · 一个 Session，多个网关

```python
from itertools import cycle
import requests

GATEWAYS = cycle([
    "http://proxy-a.example.invalid:8080",
    "http://proxy-b.example.invalid:8080",
])

with requests.Session() as session:
    session.trust_env = False
    for url in ("https://example.com/", "https://example.com/robots.txt"):
        gateway = next(GATEWAYS)
        response = session.get(url, proxies={"http": gateway, "https": gateway}, timeout=(10, 20))
        print(gateway, url, response.status_code)
```

## 弄清 timeout 度量的是什么

元组分别提供连接超时和读取超时。读取超时限制的是等待套接字数据的时间；它不是整个下载的总期限。当整个任务必须在固定时间内完成时，在任务运行器中另设一个墙钟预算。上面的诊断以流式方式打开并关闭响应，而不下载完整的响应体。

把 trust_env 设为 False 也会禁用 Requests 从环境派生的 CA 信任包设置。如果你的组织使用自定义信任包，用 verify 显式传入其批准的文件。不要用 verify=False 来让失败的测试通过。

## 解读错误：ProxyError、407 与超时

代理故障如何呈现取决于目标协议。对于 https:// 目标，故障发生在 CONNECT 隧道阶段，Requests 会抛出 requests.exceptions.ProxyError，其消息包含代理的回复，例如 Tunnel connection failed: 407 Proxy Authentication Required。对于普通 http:// 目标则没有隧道，因此 407 会作为一个 status_code 为 407 的普通 Response 到达，完全不会抛出异常；需要显式检查它。

在添加重试逻辑之前，先在 curl 中运行相同的网关和目标站点。记录异常类、尝试次数和耗时，并去掉凭据。可复现的认证错误需要修改配置；在更高并发下重复它只会增加噪音。

- 带 407 的 ProxyError：代理拒绝了 URL 中的凭据。重新检查编码和提供商的用户名格式。
- 带 Cannot connect to proxy 或名称解析消息的 ProxyError：网关主机或端口错误，或本网络无法访问它。
- ConnectTimeout：超时元组中的连接部分在代理或目标站点应答之前到期。ReadTimeout：连接成功，但在读取限制内没有数据到达。
- 隧道成功后的 SSLError：目标站点的证书验证失败，或代理正在拦截 TLS。保持验证开启并向提供商确认。
- 仅凭一次成功的 HTTP 请求无法验证出口的位置。

## 上线之前

- 使用项目虚拟环境。
- 将凭据与网关分开编码。
- 明确决定环境是否可以参与代理设置。
- 除网络超时外，再保留一个任务期限。

## 参考来源与延伸阅读

- [Requests: proxies, environment configuration and SOCKS](https://requests.readthedocs.io/en/latest/user/advanced/#proxies)
- [Requests: timeouts and errors](https://requests.readthedocs.io/en/latest/user/quickstart/#timeouts)
- [Requests API: Session.trust_env and Session.proxies](https://requests.readthedocs.io/en/latest/api/#requests.Session.trust_env)
- [urllib3: proxies and tunneling](https://urllib3.readthedocs.io/en/stable/advanced-usage.html#proxies)
- [Python: urllib.request.getproxies and environment variables](https://docs.python.org/3/library/urllib.request.html#urllib.request.getproxies)
- [Python: URL parsing and quoting](https://docs.python.org/3/library/urllib.parse.html)

## 相关指南

- [在 curl 中使用代理：-x、环境变量、SOCKS5 与认证](https://ipvolt.com/zh/guides/curl-proxy-setup.md)
- [代理环境变量：HTTP_PROXY 与 NO_PROXY](https://ipvolt.com/zh/guides/proxy-environment-variables.md)
- [一次一个阶段地排查代理超时](https://ipvolt.com/zh/guides/proxy-timeout-troubleshooting.md)

## 关于 ipvolt

示例使用通用的代理设置，并附上原始技术文档链接。具体产品的行为请向你的服务商确认。ipvolt 仍在开发中。

[阅读英文原文](https://ipvolt.com/guides/python-requests-proxy.md)

## 了解何时开放体验。

ipvolt · 开发中

我们正在为开发者和数据团队打造代理基础设施。加入意向名单，ipvolt 就绪时第一时间收到通知。

开放体验时仅发一封通知邮件，不发送其他邮件。

[申请抢先体验](https://ipvolt.com/zh/guides/python-requests-proxy#waitlist-closing)

[隐私政策](https://ipvolt.com/privacy)

