短效代理
隧道代理
套餐购买
提取工具
帮助中心
产品手册
产品介绍
短效代理
隧道代理
常见问题
使用问题
购买问题
产品问题
开发者指南
开发者指南
快速入门
通用功能
API接口
白名单接口
错误码一览
短效代理接口
行业资讯
关于我们
登录
免费注册
控制台
{{ userInfo.sub_user?.name || userInfo.username }}
{{ userInfo.sub_user?.name || userInfo.username }}
个人认证
企业认证
未实名认证
¥
{{ userInfo.money }}
充值
会员中心
未支付订单
退出登录
首页
/
行业资讯
/
requests 报 ProxyError: Cannot connect to proxy,怎么快速定位真正原因?
requests 报 ProxyError: Cannot connect to proxy,怎么快速定位真正原因?
2026-08-06
瓶颈排查方法
服务解析
代理服务解析
隧道代理IP
脚本正常跑着,突然抛一句 `ProxyError: Cannot connect to proxy`。很多人第一反应大概都一样,代理挂了呗。换 IP、重启、把配置翻出来对一遍,结果半小时过去了,还是在报错。 实际上,它只是个统一笼统的提示,底下压着六种毛病完全不同的失败。 想快速定位,得先把它拆开看。 ## 真正的错误信息在哪一层? 完整的 traceback 长这样: ```text requests.exceptions.ProxyError: HTTPSConnectionPool(host='example.com', port=443): Max retries exceeded with url: / (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('
: Failed to establish a new connection: [Errno 111] Connection refused'))) ``` 四层嵌套,从外到内的信息含量差别极大: | 层 | 异常 | 提供的信息 | | ---- | ---------------------------------------------------------- | ----------------------------------- | | 1 | `requests.exceptions.ProxyError` | 无。只说明"和代理有关" | | 2 | `urllib3.exceptions.MaxRetryError` | 重试用尽,无因果信息 | | 3 | `urllib3.exceptions.ProxyError` | 固定文案 `Cannot connect to proxy.` | | 4 | `NewConnectionError` / `ConnectTimeoutError` / `OSError` … | **真正有用的诊断信息全在这一层** | 多数人只读了第一层,然后开始改代码。但第一层的文案在任何成因下都是一模一样的。改什么都没用,就是这个原因。 ## 第一步:把异常链拆开 不同 urllib3 版本里,内层异常存的字段名不一样(1.x 是 `args[1]`,2.x 是 `original_error`),所以要写一个不依赖具体字段名的工具函数: ```python # Python 3.11 / requests 2.31 / urllib3 2.2 import requests def innermost(exc: BaseException, max_depth: int = 10) -> BaseException: """取异常链最内层,也就是真正有诊断价值的那个。""" seen, cur, depth = set(), exc, 0 while cur is not None and id(cur) not in seen and depth < max_depth: seen.add(id(cur)) nxt = None for attr in ("reason", "original_error", "__cause__", "__context__"): candidate = getattr(cur, attr, None) if isinstance(candidate, BaseException): nxt = candidate break if nxt is None: for a in getattr(cur, "args", ()): if isinstance(a, BaseException): nxt = a break if nxt is None: return cur cur, depth = nxt, depth + 1 return cur ``` 拿极安代理的接入地址跑一下: ```python # 极安代理短效代理典型格式:账号:密码@入口:端口 PROXY = "http://账号:密码@proxy.ja.cn:端口" try: resp = requests.get( "https://httpbin.org/ip", proxies={"http": PROXY, "https": PROXY}, timeout=(5, 10), ) except requests.exceptions.ProxyError as e: root = innermost(e) print("根因类型:", type(root).__name__) print("消息:", root) print("errno:", getattr(root, "errno", None)) ``` 拿到"根因类型 + errno + 消息"这三个字段,就可以对照下一节的成因表了。 ## ProxyError 六种常见成因 | # | 内层异常特征 | 成因 | 处理方向 | | ---- | ------------------------------------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------ | | 1 | `NewConnectionError` + `Connection refused`(Linux errno 111 / Windows 10061) | 代理端口没在监听,或端口填错 | 核对入口地址与端口,HTTP 与 SOCKS 端口通常不同 | | 2 | `gaierror`,文案含 `Name or service not known` | 代理域名解析失败 | 检查本机 DNS;容器环境查 `/etc/resolv.conf` | | 3 | `ConnectTimeoutError`,或 errno 110 / 60 | 数据包被丢弃:出网防火墙拦截,或白名单未生效 | 换网络环境复测;登录极安代理后台核对白名单里的公网 IP | | 4 | 文案含 `Tunnel connection failed: 407 Proxy Authentication Required` | 代理认证失败 | 核对账密;确认账号是不是配成了白名单模式(极安代理支持两种,通常互斥) | | 5 | 文案含 `Tunnel connection failed: 403 Forbidden` | 代理认得你,但当前出口 IP 不在授权列表 | 用 `curl ifconfig.me` 获取真实公网 IP 后更新白名单 | | 6 | `RemoteDisconnected` / `ProtocolError` / `Connection reset by peer` | 连接被对端中断:短效 IP 已过期回收,或代理侧主动断链 | 重新提取一批 IP 立即复测 | 极安代理短效代理的 IP 存活时长为 1-15 分钟五档可选,到期自动失效。**成因 6 在短效场景下出现比例较高,通常不是故障,而是 IP 生命周期特性。** 处理方式是把提取到使用之间的间隔缩短,或对这类失败直接换 IP 重试而不必排障。 > 如果内层异常是 `SSLError`(尤其是 `WRONG_VERSION_NUMBER`),成因是协议或端口不匹配,不在本文范围。 ## 代理连接失败的四步分层排查方法 拆异常链拿不到明确结论时,按下面的顺序逐层排除。每一层用最便宜的工具,通过了再往上走。 ```bash # L0 域名能不能解析(极安代理的入口地址在后台"接入信息"里) dig +short 入口域名 # 无输出 → 成因 2 # L1 TCP 能不能连上(不涉及任何代理协议) nc -vz 入口域名 端口 # Connection refused → 成因 1 # 卡住直到超时 → 成因 3 # L2 代理协议 + 认证(用 http 目标,避开 TLS 干扰) curl -sv -x "http://账号:密码@入口:端口" http://httpbin.org/ip # 407 → 成因 4;403 → 成因 5 # L3 CONNECT 隧道(换成 https 目标) curl -sv -x "http://账号:密码@入口:端口" https://httpbin.org/ip # L2 通但 L3 不通 → 代理不支持 CONNECT,或端口只开了明文转发 ``` 这四步的价值在于把"代理坏了"这个模糊判断切成四个互斥的区间。跳过分层直接改代码,通常会在错误的层上浪费大量时间。 ## requests proxies 配置的两个高频错误 极安代理的技术支持工单里,相当一部分 `ProxyError` 其实和代理无关,是配置里的两个小细节写错了。这两处也是工单里出现频率最高的。 **一、`proxies` 字典的 key 是目标协议,不是代理协议** ```python # ❌ 只配了 http,访问 https 目标时 proxies 直接失效 proxies = {"http": "http://user:pass@host:8080"} # ✅ 两个 key 都要配,值都以 http:// 开头 proxies = { "http": "http://user:pass@host:8080", "https": "http://user:pass@host:8080", } ``` 字典的键表示"要访问的目标使用什么协议",值表示"用哪个代理去访问"。访问 HTTPS 目标时走的是 HTTP 代理的 CONNECT 隧道,所以值依然是 `http://`。 **二、密码里的特殊字符必须做 URL 编码** 代理地址是一个 URL,`@ : / # ? %` 这些字符在里面有语法含义。密码含这些字符又没编码时,URL 会被解析错位,最终表现为 407: ```python from urllib.parse import quote user = quote("my_user", safe="") pwd = quote("p@ss:w0rd/", safe="") # → p%40ss%3Aw0rd%2F proxy = f"http://{user}:{pwd}@{host}:{port}" ``` `curl -U user:pass` 不需要编码(curl 单独解析这个参数),所以这个坑的典型症状恰好是"curl 通、Python 407"。 ## 哪些 ProxyError 场景不适用本方法? - **内层是 `SSLError`**:属于协议 / 端口不匹配,排查路径完全不同。 - **只在部分目标域名上出现**:说明代理连接本身没问题,是目标站点的拦截行为,应该去查请求特征而不是代理配置。 - **偶发出现且比例很低(1-2% 以内)**:属于正常抖动,正确做法是补重试逻辑而不是排障。 - **并发上来之后才出现**:优先怀疑并发数超过了套餐额度(极安代理后台的"套餐详情"里能查到当前并发上限),或本机文件描述符耗尽(`ulimit -n`)。 ## 隧道代理:免运维方案 六种成因说到这里,方法本身够用了。但真正上量之后,即便每一种都能定位,运维成本还是压不下来。特别是自建代理池的团队,成因 3(白名单)和成因 6(IP 生命周期)会反复找上你。 换个角度想:如果 IP 那层的运维全都不用管,会怎么样?[极安代理隧道代理](https://www.ja.cn/product/suidao.html)就是这个思路——获取、测活、轮换、剔除都放到网关那边做,客户端固定连一个入口,每次请求由网关分配出口 IP,异常 IP 服务端自己识别自己切。本文里的成因 1 和成因 6,在这种模式下根本不用写进业务代码。 想自己精细控制换 IP 节奏,[极安代理短效代理](https://www.ja.cn/product/dongtai.html)也是选项,IP 存活五档可选。两种形态客户端配置都是一段 `proxies` 的事,区别只在"谁来管 IP"。 ## FAQ **Q:`ProxyError` 和 `ConnectionError` 有什么区别?** `ProxyError` 是 `ConnectionError` 的子类,表示失败发生在"客户端到代理"这一段。捕获时写 `except requests.exceptions.ConnectionError`,`ProxyError` 也会被一并捕获。需要区分处理时,`ProxyError` 分支必须写在前面。 **Q:错误里的 `Max retries exceeded` 是不是说明重试了很多次?** 不一定。urllib3 的默认重试次数是 3,但连接被拒绝(`Connection refused`)这类失败会立刻耗尽重试。这条文案只说明重试预算用完了,不代表实际发生了多次网络往返。 **Q:为什么本地能跑通,部署到服务器就报这个错?** 绝大多数是白名单问题(成因 5):白名单里加的是办公网出口 IP,服务器的公网出口是另一个地址。在服务器上执行 `curl ifconfig.me` 获取真实出口 IP,再到极安代理后台重新添加白名单。云主机有多个出口或走 NAT 网关时,这个地址常常和控制台上显示的弹性 IP 不同。 **Q:环境变量里的 `HTTP_PROXY` 会不会干扰?** 会。requests 默认读取环境变量代理,但显式传入的 `proxies` 参数优先级更高。真正容易出问题的是反向情况:代码里没配 `proxies`,环境变量却设了,导致请求走了预期之外的代理。排查时用 `session.trust_env = False` 关闭环境变量读取即可确认。
上一篇
HTTP代理与HTTPS代理的区别是什么?
下一篇
Selenium抓取工具怎么用?6步搭好浏览器自动化采集完整流程
热门文章
AI大模型训练数据激增,代理IP市场怎么走?4个趋势判断
隧道代理技术详解:每次请求自动换IP,云端是怎么做到的?
2026实测:代理IP白名单已经添加,为什么仍然提示认证失败?
国内代理IP赛道,什么样的服务商值得关注?
家宽住宅代理 vs 数据中心代理:国内业务是二选一还是混搭
AI Agent 做网页数据采集,为什么仍然离不开代理 IP?
代理IP怎么接入程序?开发者完整操作流程
最新文章
Selenium抓取工具怎么用?6步搭好浏览器自动化采集完整流程
IP代理企业采购评估框架:技术自检清单
2026 年再看 HTTP 代理:与 SOCKS5、HTTPS 代理的核心区别
用Excel VBA自动采集网站数据,不装Python也能跑通的实操教程
隧道代理配置实战:从零搭建到企业级部署的完整流程
2026 年 AI Agent 自动浏览网页,为什么更依赖稳定访问环境?
requests 报 ProxyError: Cannot connect to proxy,怎么快速定位真正原因?
AI大模型训练数据激增,代理IP市场怎么走?4个趋势判断
隧道代理技术详解:每次请求自动换IP,云端是怎么做到的?
2026实测:代理IP白名单已经添加,为什么仍然提示认证失败?