# 407 代理身份验证要求：每个原因及其解决方法

HTTP 407 只有一个含义：前面的代理拒绝了您的凭据。这个单一事实消除了大多数错误的方向——这里是剩下的地图。

HTTP 407 代理身份验证要求只有一个含义，比大多数人想象的要狭窄：一个位于您和互联网之间的代理拒绝了请求，因为它缺乏有效的凭据*针对代理本身*。目标网站从未被联系。它从未看到您的请求，从未做出决定，也不可能是原因。因此，修复 407 总是意味着修复您的代理配置——可以出错的事情列表很短且完全可枚举。本指南涵盖了整个列表，包括最容易让人困惑的工具特定修复。

## 首先阅读 Proxy-Authenticate 头

根据 HTTP 规范 (RFC 9110)，407 必须伴随一个描述如何进行身份验证的`Proxy-Authenticate`头——通常是类似`Proxy-Authenticate: Basic realm="Access to internal site"`的内容。然后，您的客户端应重复请求并带有`Proxy-Authorization`头。这个配对值得记住，因为它是 407 与其邻居的区别：**401** 来自源服务器，并将`WWW-Authenticate`与`Authorization`配对，而**407**来自中介，并使用`Proxy-`前缀版本。如果您盯着`WWW-Authenticate`头，您正在调试错误的跳跃。

```bash
# See exactly which hop is refusing you, and what scheme it wants
curl -v -x http://USER:PASS@residentialpremium.quantumproxies.io:8080 https://httpbin.org/ip

# Response you are looking for on failure:
#   HTTP/1.1 407 Proxy Authentication Required
#   Proxy-Authenticate: Basic realm="..."
#
# Response you want on success: your exit IP, not your own
#   {"origin": "203.0.113.45"}
```

如果`curl -x`带凭据返回您的出口 IP，代理和凭据都没问题——您在应用程序中仍然看到的任何 407 都是该应用程序自己的配置，而不是代理的。这个简单的测试在大约十秒钟内将问题一分为二。

## 原因 1：凭据缺失、错误或位置错误

最常见的原因也是最无聊的。凭据属于代理 URL，在主机之前，以`user:pass@host:port`形式——客户端库从中构建`Proxy-Authorization`头。从仪表板复制一个端点而没有凭据，或者粘贴您的帐户密码而不是代理密码（它们通常不同），会在每个请求上立即产生永久的 407。

```python
import requests

proxy = "http://USER:PASS@residentialpremium.quantumproxies.io:8080"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=15)
print(r.status_code, r.json())   # 200 and the exit IP = auth is correct
```

也要检查端口。提供商为旋转和粘性端点以及 HTTP 与 SOCKS5 暴露不同的端口；即使凭据有效，命中错误的端口仍可能返回 407，因为该监听器期望不同的身份格式。如果您不确定您使用的是哪个协议，我们关于[SOCKS5 与 HTTP 代理](https://quantumproxies.io/blog/socks5-vs-http-proxy-difference)的解释说明了区别。

## 原因 2：从未进行百分比编码的特殊字符

这一个让人们浪费了整个下午。代理 URL 是一个 URL，因此用户名或密码中的任何保留字符都必须进行百分比编码，否则解析器会在错误的位置拆分字符串。包含`@`的密码会提前结束用户信息部分，您的客户端尝试连接到不存在的主机；`:`在错误的位置将用户名与密码分开。

- `@`变为`%40`——最常见的罪魁祸首，因为电子邮件被用作用户名。
- `:`变为`%3A`——否则它会被读取为用户名/密码分隔符。
- `#`变为`%23`——其后的所有内容被视为片段并被静默丢弃。
- `/`变为`%2F`，`?`变为`%3F`——两者都结束了权限部分。
- 一个字面上的空格变为`%20`。如果您的密码中有一个，请更改它。

```python
from urllib.parse import quote

user = quote("team@example.com", safe="")   # team%40example.com
pwd  = quote("p@ss:w#rd", safe="")          # p%40ss%3Aw%23rd

proxy = f"http://{user}:{pwd}@residentialpremium.quantumproxies.io:8080"
```

![按检查顺序排列的 407 原因：凭据缺失或错误、特殊字符未编码、白名单 IP 发生了变化、未认证的 HTTPS CONNECT 隧道，以及有自己代理配置的工具；卡片把每个症状（例如只有 https URL 出现 407）对应到其原因。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335152/blog/generated/qp-b9-014-diag1.png)
*相同的状态代码，五种不同的故障。在更改任何内容之前，请先匹配左侧的症状。*

## 原因 3：白名单身份验证和移动的 IP

大多数提供商支持两种身份验证模式：URL 中的凭据或 IP 白名单，您在仪表板中授权服务器的公共地址，并且不发送任何凭据。QuantumProxies 支持两者。故障模式是特定且非常可识别的：一切工作了几周，然后每个请求开始返回 407 而没有代码更改。这是您的公共 IP 更改——办公室的 DHCP 租约续约，云重新部署后的新 NAT 网关，移动网络共享，或每个作业获取新地址的 CI 运行器。

在调试其他任何内容之前确认这一点：使用`curl -sS https://api.ipify.org`获取您当前的公共地址，将其与白名单进行比较，如果不同则重新添加。如果您的出口 IP 不稳定——CI 运行器和自动缩放组很少稳定——将该环境切换到`user:pass`身份验证，它随配置而不是网络一起传输。这个陷阱的另一半是混合模式：一些网关在仅白名单端点上拒绝凭据，因此发送两者可能会失败，而发送都不发送则成功。

## 原因 4：HTTPS 通过 CONNECT 隧道

仅在`https://` URL 上出现的 407，通常作为 Python 错误`OSError: Tunnel connection failed: 407 Proxy Authentication Required`，具有结构性原因。普通 HTTP 请求由代理转发，但 HTTPS 请求首先通过`CONNECT`请求打开一个隧道——而该 CONNECT 携带自己的`Proxy-Authorization`头。如果您的配置仅设置了 HTTP 代理，或在一个方案上设置了凭据而不是另一个，隧道将匿名尝试并在 TLS 开始之前被拒绝。

规则很简单：始终使用相同的凭据配置两个方案。在 Python 中，这意味着`proxies`字典中的两个键；在 shell 中，这意味着`HTTP_PROXY`和`HTTPS_PROXY`；在 npm 中，这意味着`proxy`和`https-proxy`。请注意，`HTTPS_PROXY`几乎总是采用`http://`方案——该方案描述了您如何与代理通信，而不是您通过它获取的内容。

```js
// Node 18+ with undici: one dispatcher covers http and https targets
import { ProxyAgent, fetch } from "undici";

const dispatcher = new ProxyAgent(
  "http://USER:PASS@residentialpremium.quantumproxies.io:8080"
);

const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(res.status, await res.json());
```

## 原因 5：工具有自己的代理配置

环境变量并非通用。许多工具读取自己的配置文件并完全忽略 shell，这产生了令人恼火的状态，即`curl`工作而您的构建不工作。一个长期存在的 GitHub Desktop 问题是教科书式的例子：一个开发人员在公司代理后面设置了`.gitconfig`和环境中的代理，但登录仍然失败，出现 407 和`net::ERR_TUNNEL_CONNECTION_FAILED`——因为 git 配置仅对 git 进行身份验证，而进行 OAuth 流程的嵌入式浏览器没有自己的代理凭据。每个子系统都需要单独告知。

```bash
# shell-wide (respected by curl, wget, pip, most SDKs)
export HTTP_PROXY="http://USER:PASS@residentialpremium.quantumproxies.io:8080"
export HTTPS_PROXY="$HTTP_PROXY"
export NO_PROXY="localhost,127.0.0.1,.internal"

# npm - both keys, or https installs will 407
npm config set proxy       "$HTTP_PROXY"
npm config set https-proxy  "$HTTPS_PROXY"

# git
git config --global http.proxy  "$HTTP_PROXY"
git config --global https.proxy "$HTTPS_PROXY"

# apt - /etc/apt/apt.conf.d/95proxies
# Acquire::http::Proxy  "http://USER:PASS@residentialpremium.quantumproxies.io:8080";
# Acquire::https::Proxy "http://USER:PASS@residentialpremium.quantumproxies.io:8080";
```

- **Postman**——设置，代理，自定义代理配置，然后勾选代理身份验证并填写用户名和密码。系统代理切换不携带凭据。
- **.NET / C#**——读取"远程服务器返回错误：(407)"的`WebException`意味着`WebProxy`没有`Credentials`；明确设置它们或使用默认网络凭据。
- **Java**——`http.proxyUser`和`http.proxyPassword`系统属性，加上一个`Authenticator`，因为 JVM 不读取 shell 变量。
- **浏览器**——修复凭据后，缓存的 407 可能会持续存在；在假设修复失败之前，强制重新加载或清除缓存。
- **Docker**——守护进程和构建都需要代理设置，并且它们在不同的地方配置。

在编辑所有这些文件时的一项安全提示：全局 git 或 npm 配置中的凭据最终以明文形式出现，嵌入密码的代理 URL 会泄漏到 shell 历史记录、CI 日志和错误跟踪中。在具有稳定地址的机器上，IP 白名单完全避免了秘密。

![两种代理认证方式并列：user:pass 凭据随配置走，但它是可能泄漏的密钥；IP 白名单随网络走，不需要任何密钥；卡片按环境选择：CI 运行器和自动扩缩容用凭据，稳定的服务器用白名单，绝不两者同时使用。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335153/blog/generated/qp-b9-014-diag2.png)
*凭据随您的配置一起传输；白名单随您的网络一起传输。根据环境选择，永远不要同时选择两者。*

## 407 从来不是目标站点的错

值得重申，因为它可以让您免于追逐幽灵。如果您收到 407，无论旋转用户代理、添加头还是更改出口国家都无济于事——请求尚未离开您的代理。从目标站点来的阻止看起来不同：[403 Forbidden](https://quantumproxies.io/blog/fix-403-forbidden-web-scraping)表示站点拒绝了您，而[429 Too Many Requests](https://quantumproxies.io/blog/fix-429-too-many-requests-scraping)表示您速度太快。在编写任何代码之前，诊断您实际拥有的三者中的哪一个。如果 Python 抛出`ProxyError`或`SSLError`而不是干净的 407，我们的[调试 Requests 中的 ProxyError](https://quantumproxies.io/blog/python-requests-proxyerror-fix)指南涵盖了传输级别的故障。

## 常见问题解答

### 如何解决 407 代理身份验证要求？

将有效的凭据放在代理 URL 中作为`http://user:pass@host:port`，对任何保留字符进行百分比编码，并配置 HTTP 和 HTTPS 代理设置。如果您的提供商使用 IP 白名单，请授权您当前的公共 IP 并不发送凭据。在触及您的应用程序代码之前，使用`curl -x`对 IP 回显服务进行验证。

### 407 代理身份验证要求是什么意思？

这意味着中介代理因缺乏有效的代理凭据而拒绝了请求。响应包括一个`Proxy-Authenticate`头，命名方案，客户端应重试并带有`Proxy-Authorization`。它与 401 不同，401 来自目标服务器，而不是中间的代理。

### 如何修复 npm 错误 407？

设置两个键：`npm config set proxy`和`npm config set https-proxy`，每个都有完整的`http://user:pass@host:port` URL。注册表流量是 HTTPS，因此仅 HTTP 设置在 CONNECT 隧道处失败。对密码中的特殊字符进行百分比编码，并检查是否有项目级`.npmrc`覆盖您的全局配置。

### 为什么 Python 会引发 Tunnel connection failed: 407？

因为 HTTPS 请求打开了一个没有携带代理凭据的 CONNECT 隧道。将`proxies`字典中的`http`和`https`键都设置为相同的认证 URL。还要检查环境中的`HTTP_PROXY`或`HTTPS_PROXY`是否覆盖了您的字典——设置`session.trust_env = False`以排除这一点。

### 如何在 Postman 中设置代理身份验证？

打开设置，转到代理选项卡，启用自定义代理配置，输入主机和端口，然后勾选代理身份验证框并添加用户名和密码。依赖于系统代理切换是常见错误——它通过代理路由流量但从不提供凭据，因此每个请求都返回 407。

五个原因几乎涵盖了所有 407：缺少凭据、未编码的特殊字符、已更改的白名单 IP、未经身份验证的 CONNECT 隧道以及具有自身配置的工具。按此顺序处理它们，状态代码就会消失——然后您可以开始担心目标站点对您的看法。

[获取具有用户：pass 或 IP 白名单身份验证的住宅代理](https://quantumproxies.io/residential-proxies)
