实操教程2026年9月29日阅读约 7 分钟

407 代理认证错误怎么解决

407 代理认证错误(Proxy Authentication Required)表示代理拒绝了你的登录。用 curl -v 找到原因,再按 curl、Python、Node 分别修好。

遇到 407 代理认证错误(407 Proxy Authentication Required),意思是代理自己把你挡在了门外,请求根本没有到达目标网站。代理没有收到它认可的用户名和密码。原因几乎总在登录信息本身:密码输错或复制不全、多了看不见的空格、特殊符号没有编码,或者某个工具悄悄把凭据丢掉了。

既然网站根本没看到这个请求,目标网站、请求头、IP 信誉这些都暂时不用管。Proxy Authentication Required 怎么解决?先用一条 curl 命令确认问题出在代理这一层,再按出现频率从高到低逐个排查原因,并给出每种工具的修法。

所有代码都用 HOST、PORT、USERNAME 和 PASSWORD 作占位符。你自己的值在控制台里每项服务的页面上。

407 Proxy Authentication Required 是什么意思?

HTTP 里有两个长得很像的登录状态码。401 来自网站:页面要求你登录。407 来自中间的代理:代理要先拿到凭据,才肯替你转发。

过程是这样的:客户端向代理发请求时,带上一个 Proxy-Authorization 请求头,里面是 Base64 编码的 USERNAME:PASSWORD。如果这个头缺失,或者值对不上,代理就返回 407,并附上 Proxy-Authenticate 响应头说明它要求哪种认证方式,通常是 Basic。访问 https 网站时,这个请求是一条 CONNECT(见CONNECT 隧道),所以 407 会在与网站建立任何加密连接之前就返回。

这也是术语表里 407 词条说修复几乎总在登录信息上的原因。代理只检查两样东西,而这两样都在你手里。

用 curl -v 复现代理 407 错误

改代码之前,先确认故障出在哪一层。加上 -v,curl 会打印它和代理之间的完整对话:

curl -v -x "http://USERNAME:PASSWORD@HOST:PORT" https://api.ipify.org

密码错误时,关键的几行是这样的:

* Proxy auth using Basic with user 'USERNAME'
* Establish HTTP proxy tunnel to api.ipify.org:443
> CONNECT api.ipify.org:443 HTTP/1.1
> Host: api.ipify.org:443
> Proxy-Authorization: Basic VVNFUk5BTUU6d3Jvbmc=
>
< HTTP/1.1 407 Proxy Authentication Required
< Proxy-Authenticate: Basic realm="proxy"
* CONNECT tunnel failed, response 407
curl: (56) CONNECT tunnel failed, response 407

怎么读:

  • 以 > 开头的行是 curl 发给代理的内容。如果根本没有 Proxy-Authorization 这一行,说明 curl 没拿到凭据,问题出在你传参的方式上。
  • 以 < 开头的行是代理的回复。这里出现 407,而且没有任何来自网站的内容,就说明是代理拒绝的。
  • 退出码 56 加上 “CONNECT tunnel failed, response 407”,是 curl 在告诉你隧道被拒绝了。如果目标是普通的 http:// 网址,407 会作为一个普通响应返回,退出码是 0。

贴到任何地方之前先注意一件事:Proxy-Authorization 的值就是你的用户名和密码的 Base64,任何人一秒钟就能解出来。分享输出之前,把这一行和 -x 后面的网址都删掉。

如果 curl 能成功,而你的程序还是 407,说明凭据本身没问题,是程序发送凭据的方式不一样。直接跳到下面按工具分类的修法。

常见原因,按可能性排序

1. 密码错了,或者没复制全

双击选中密码时,选区经常停在某个符号前,只复制了一半。贴进聊天软件的密码可能被改了格式。重新生成凭据之后,旧密码还留在某个配置文件里。用服务页面上的复制按钮重新复制密码,粘贴到能完整看见的地方核对一遍。

2. 看不见的空白字符

结尾的空格、从文件里读出来的换行符、Windows 下保存的 .env 文件带的 \r,都会变成密码的一部分。代理逐字节比较,所以 PASSWORD 和 PASSWORD 是两个不同的登录。在 Python 里,凡是从文件或环境变量读出来的值都 .strip() 一下:

import os

PASSWORD = os.environ["PROXY_PASSWORD"].strip()

3. 需要百分号编码的符号

在 URL 里,有些字符是有用途的。@ 分隔登录信息和主机,: 分隔用户名和密码、主机和端口,/、#、? 和 % 也各有含义。密码里只要含有其中之一,URL 在到达代理之前就已经坏了。有时解析器会直接报错,比如密码里有 / 时,curl 会这样:

curl: (5) Unsupported proxy syntax in 'http://USERNAME:pa/ss@HOST:PORT': Port number was not a decimal number between 0 and 65535

有时它会一声不响地读成另一个密码。最隐蔽的是 % 后面跟两位十六进制数字:curl、requests 和 undici 都会把 ab%41cd 解码成 abAcd 发出去,然后收到 407,没有任何提示。

解决办法是先对用户名和密码做百分号编码,再拼进 URL。Python 写法:

from urllib.parse import quote

import requests

user = quote("USERNAME", safe="")
password = quote("PASSWORD", safe="")
PROXY = f"http://{user}:{password}@HOST:PORT"

r = requests.get("https://api.ipify.org", proxies={"http": PROXY, "https": PROXY}, timeout=30)
print(r.text)

safe="" 不能省:quote 默认不编码 /,而它恰好是需要编码的字符之一。JavaScript 里对应的是 encodeURIComponent,见下面的 Node 部分。

4. 凭据发到了别的服务或端口

我们没有一个所有产品共用的网关地址。控制台里每项服务都有自己的主机、端口、用户名和密码,每个 ISP 或数据中心 IP 也各自列出端口和登录信息。把住宅代理的登录发到数据中心的端口,或者把一个 IP 的凭据和另一个 IP 的端口拼在一起,哪怕每个字符都对,也会得到 407。四个值请从同一行复制。顺便在那个页面确认服务仍显示为有效。

5. 粘性凭据只复制了一部分

住宅代理服务设成“粘性 IP”时,控制台会生成一个带会话 ID 的凭据。它比普通凭据长,很容易只复制一部分。请按控制台显示的样子完整复制。什么时候才需要这种模式,见轮换代理与粘性代理。

6. 工具把凭据丢了

“curl 能用,我的代码不行”,多半是这个原因。常见的几种:

  • requests 的 auth= 是发给网站的,不是发给代理的。 requests.get(url, proxies={"https": "http://HOST:PORT"}, auth=(...)) 照样得到 407。代理的登录信息要写在代理 URL 里。
  • 环境变量有大小写两种写法。 对 http:// 网址,curl 只读小写的 http_proxy,会忽略 HTTP_PROXY。对 https:// 网址,https_proxy 和 HTTPS_PROXY 它都读,两者同时存在时小写的优先。Python 的 requests 也是这样。shell 配置文件里残留的旧 https_proxy,会悄悄盖过你刚刚 export 的 HTTPS_PROXY。运行 env | grep -i proxy 看看到底设了什么。
  • 浏览器会忽略代理设置里的 user:pass。 浏览器的代理设置只填主机和端口,登录信息由浏览器弹窗询问。Chrome 的 --proxy-server 参数完全不接受用户名和密码,用这种方式启动的无头 Chrome 没法回应弹窗,只能失败。桌面浏览器的配置见浏览器接入指南,在代码里提供登录信息的方法见 Selenium 接入指南。

按工具修复

curl

用 -U 传登录信息,不写进 URL。curl 会原样发送,符号不需要编码:

curl -x "http://HOST:PORT" -U "USERNAME:PASSWORD" https://api.ipify.org

如果这样能通而 URL 写法不行,问题就是编码。其他退出码的含义见 cURL 接入指南。

Python requests

像第 3 条那样用 quote(..., safe="") 构造代理 URL,从文件读出的值先去掉空白,登录信息写在代理 URL 里。目标是 https 时,407 会以异常的形式出现,而不是一个响应:

ProxyError: ... (Caused by ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 407 Proxy Authentication Required')))

同样的登录信息访问 http:// 目标时,会返回一个普通的 Response,status_code == 407。原因相同,表现不同。完整配置见 Python requests 接入指南。

Node.js:undici 或 axios

用 undici 的 ProxyAgent 时,两部分都编码后再写进 URL:

import { fetch, ProxyAgent } from 'undici';

const user = encodeURIComponent('USERNAME');
const password = encodeURIComponent('PASSWORD');
const dispatcher = new ProxyAgent(`http://${user}:${password}@HOST:PORT`);

try {
  const res = await fetch('https://api.ipify.org', { dispatcher });
  console.log(await res.text());
} catch (err) {
  console.error(err.cause?.cause ?? err.cause ?? err);
}

undici 把 407 报成 TypeError: fetch failed,光看这一句什么也看不出来。真正的信息 Proxy response (407) !== 200 when HTTP Tunneling 藏在往下两层的 err.cause.cause 里,所以示例把它打印出来。

axios 用对象传登录信息,不需要编码:

import axios from 'axios';

const res = await axios.get('https://api.ipify.org', {
  proxy: {
    protocol: 'http',
    host: 'HOST',
    port: Number('PORT'),
    auth: { username: 'USERNAME', password: 'PASSWORD' },
  },
});
console.log(res.data);

登录信息错误时,这里会抛出 AxiosError: Request failed with status code 407。https-proxy-agent 的写法见 Node.js 接入指南。

快速问答

407 是网站在封我吗? 不是。407 来自代理,发生在联系网站之前。网站的封锁表现为 403、429 或验证码页面,这些见爬虫为什么突然开始被封了。

为什么 curl 能用,我的脚本却是 407? 凭据没错,是脚本发送的方式不同:符号没编码、文件里带了空白、环境变量盖掉了你的设置,或者 auth= 发给了网站。

为什么 https 网址报异常,http 网址却返回 407 响应? 访问 https 时,客户端要先建立 CONNECT 隧道,隧道被拒就是一个错误。访问普通 http 时,代理的 407 作为普通响应返回。

换个密码能解决吗? 只有旧密码本身错了或泄露了才有用。如果新密码里有符号,记得编码或改用 -U,不然还会回到这里。

还是没解决?

运行上面的 curl -v 命令,删掉 Proxy-Authorization 那一行和 -x 后面的网址,把剩下的内容连同你用的工具一起贴到 Discord。如果你遇到的其实是卡住不动而不是被拒绝,下一步看代理超时错误。

还有后续问题?

去 Discord 问。答案还能帮到下一个读到这个帖子的人。

加入 Discorddiscord.gg/proxypanda
$5 起步去 Discord 问