HTTP 407 Proxy Authentication Required
Quick reference
| Code | 407 |
|---|---|
| Name | Proxy Authentication Required |
| Category | 4xx Client Error |
| Spec | RFC 9110 §15.5.8 |
| Required header | Proxy-Authenticate: in response |
What 407 means
HTTP 407 Proxy Authentication Required is the proxy-level equivalent of 401 Unauthorized. When a client sends a request through an HTTP proxy and the proxy requires authentication before forwarding the request, the proxy returns 407 with a Proxy-Authenticate: header describing the authentication scheme and realm.
The key architectural distinction from 401: 407 is generated and consumed by the proxy, not the origin server. The origin server never sees the failed request. The client must include a Proxy-Authorization: header with credentials on the retry — analogous to how Authorization: is used with 401 and origin server challenges.
RFC 9110 §15.5.8 requires the 407 response to include a Proxy-Authenticate: header. The value is an authentication challenge in the same format as WWW-Authenticate: — for example: Proxy-Authenticate: Basic realm="Corporate Proxy".
Complete challenge-response flow
# Step 1: Client sends request through proxy without credentials GET https://api.example.com/data HTTP/1.1 Host: api.example.com # Step 2: Proxy challenges with 407 HTTP/1.1 407 Proxy Authentication Required Proxy-Authenticate: Basic realm="Corporate Proxy" Content-Length: 0 # Step 3: Client encodes credentials (username:password → base64) # "proxyuser:secret" → "cHJveHl1c2VyOnNlY3JldA==" # Step 4: Client retries with Proxy-Authorization header GET https://api.example.com/data HTTP/1.1 Host: api.example.com Proxy-Authorization: Basic cHJveHl1c2VyOnNlY3JldA== # Step 5: Proxy forwards to origin and returns the response HTTP/1.1 200 OK Content-Type: application/json ...
Once authenticated, the proxy typically maintains the authentication state for the connection lifetime or a session window, so subsequent requests on the same connection do not need to repeat the Proxy-Authorization header.
Client-side configuration
curl:
# Basic auth through proxy curl -x http://proxy.corp.example.com:8080 --proxy-user proxyuser:secret https://api.example.com/data # NTLM proxy auth (common in corporate Windows environments) curl -x http://proxy.corp.example.com:8080 --proxy-ntlm --proxy-user "DOMAIN\username:password" https://api.example.com/data
Python requests:
import requests
proxies = {
'http': 'http://proxyuser:secret@proxy.corp.example.com:8080',
'https': 'http://proxyuser:secret@proxy.corp.example.com:8080',
}
response = requests.get('https://api.example.com/data', proxies=proxies)
print(response.status_code)
Environment variables (used by curl, Python requests, Go net/http, and many other clients automatically):
export HTTP_PROXY="http://proxyuser:secret@proxy.corp.example.com:8080" export HTTPS_PROXY="http://proxyuser:secret@proxy.corp.example.com:8080" export NO_PROXY="localhost,127.0.0.1,.internal.example.com"
Node.js (https-proxy-agent):
import { HttpsProxyAgent } from 'https-proxy-agent';
import fetch from 'node-fetch';
const agent = new HttpsProxyAgent('http://proxyuser:secret@proxy.corp.example.com:8080');
const res = await fetch('https://api.example.com/data', { agent });
console.log(await res.json());
Corporate proxy environments
407 is most commonly encountered in corporate network environments where a mandatory forward proxy intercepts outbound HTTPS traffic for security inspection, logging, or policy enforcement. These proxies frequently use NTLM or Kerberos (Negotiate) authentication tied to Active Directory credentials.
NTLM authentication requires a multi-step handshake (NTLM Type 1 → Type 2 challenge → Type 3 response) rather than a single round trip. Most HTTP client libraries handle this automatically when configured with NTLM-capable proxy settings. The key is that the client library must support the specific auth scheme advertised in Proxy-Authenticate:.
In Docker and CI/CD environments, pass proxy credentials via build args or environment variables rather than hardcoding them in Dockerfiles or CI scripts. Use a secrets manager to inject HTTPS_PROXY at runtime.
407 vs 401
| Aspect | 407 Proxy Auth Required | 401 Unauthorized |
|---|---|---|
| Generated by | HTTP proxy (intermediary) | Origin server |
| Challenge header | Proxy-Authenticate: | WWW-Authenticate: |
| Credentials header | Proxy-Authorization: | Authorization: |
| Scope | Proxy access permission | Resource access permission |
| Origin server visibility | Never sees the unauthenticated request | Generates the response directly |
Frequently asked questions
Can a request return both 407 and 401?
Not in a single response, but a request can require both proxy authentication and origin authentication sequentially. After the proxy challenge (407) is satisfied with Proxy-Authorization:, the origin server may still challenge with 401 requiring an Authorization: header. These are two independent authentication layers.
Does 407 apply to HTTPS tunnels (CONNECT)?
Yes. When a client sends a CONNECT request to establish a TLS tunnel through a proxy (the mechanism used for HTTPS through HTTP proxies), the proxy may respond with 407 before establishing the tunnel. The client authenticates at the proxy level before the TLS tunnel is created, so the proxy never sees the HTTPS traffic inside the tunnel.
Why does my app get 407 in production but not in development?
Development environments often have direct internet access while production deployments route through a corporate or cloud proxy. The solution is to configure the production environment's HTTP_PROXY / HTTPS_PROXY environment variables with the correct proxy URL and credentials.
Is Proxy-Authorization secure over HTTP?
Basic proxy authentication transmits credentials base64-encoded (not encrypted) and should only be used over HTTPS tunnels. For HTTP connections, use Digest authentication or NTLM/Negotiate at minimum. In corporate environments, the proxy is typically on the LAN, limiting exposure.