< HTTP/1.1 407 Proxy Authentication Required407 Proxy Authentication Required: Fix It
407 means your proxy wants credentials before forwarding the request. Fix it in curl, npm, pip, git and browsers, and learn how Proxy-Authenticate works.
- Cacheable
- Only with explicit freshness
- Retry?
- After authenticating to the proxy
- Usually sent by
- Forward proxy
- Spec
- RFC 9110 §15.5.8
- Often confused with
- 401
On this page
TL;DR: 407 comes from a proxy, not the website. It wants credentials in a
Proxy-Authorizationheader before it will forward your request. Check which schemeProxy-Authenticateasks for, then supply credentials the tool actually supports (Basic is common; NTLM/Kerberos usually need a helper).
What it means
This is the proxy equivalent of 401. The proxy challenges you, you retry with credentials, the proxy forwards the request. RFC 9110 §15.5.8 requires the 407 to include Proxy-Authenticate.
GET http://example.com/ HTTP/1.1
Host: example.com
HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="Corp Proxy"
Content-Type: text/html
Content-Length: 0
Retry with credentials:
GET http://example.com/ HTTP/1.1
Host: example.com
Proxy-Authorization: Basic YWxpY2U6czNjcmV0
The value is base64("alice:s3cret"). Basic is not encryption. Over plain HTTP it is readable by anything on the path to the proxy, so only use it to a proxy you reach over a trusted network or TLS.
HTTPS goes through CONNECT
For https:// URLs, a client asks the proxy to open a tunnel with CONNECT, and the proxy usually challenges there:
CONNECT api.example.com:443 HTTP/1.1
Host: api.example.com:443
HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Negotiate
Proxy-Authenticate: NTLM
Proxy-Authenticate: Basic realm="Corp Proxy"
This is why the symptoms look TLS-shaped even though it is an HTTP-level refusal. You will see:
curl: (56) Received HTTP code 407 from proxy after CONNECT
pip: ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 407 Proxy Authentication Required'))
Chrome shows ERR_TUNNEL_CONNECTION_FAILED when it cannot authenticate to the proxy, or prompts for credentials if it can.
Diagnosis
- Find out which proxy is in play:
env | grep -i proxy,git config --get http.proxy,npm config get proxy, system settings, or a PAC file. - See what the proxy offers:
curl -v -x http://proxy.corp.example:8080 https://example.com/ 2>&1 | grep -i -E 'proxy-authenticate|HTTP/1.1 407'
- Read the schemes.
Basicworks with username and password in most tools.NTLMandNegotiate(Kerberos) tie to your Windows login, and most CLI tools cannot do them natively.
Fix it per tool
curl:
curl -x http://proxy.corp.example:8080 --proxy-user alice:s3cret https://example.com/
# NTLM / Negotiate
curl -x http://proxy.corp.example:8080 --proxy-ntlm --proxy-user alice:s3cret https://example.com/
curl -x http://proxy.corp.example:8080 --proxy-negotiate --proxy-user : https://example.com/
Environment variables (honoured by curl, pip, Go, Python requests and many others). Percent-encode special characters in the password:
export HTTPS_PROXY='http://alice:p%40ss%23word@proxy.corp.example:8080'
export HTTP_PROXY="$HTTPS_PROXY"
export NO_PROXY='localhost,127.0.0.1,.corp.example'
npm, pip and git:
npm config set proxy http://alice:s3cret@proxy.corp.example:8080
npm config set https-proxy http://alice:s3cret@proxy.corp.example:8080
pip install --proxy http://alice:s3cret@proxy.corp.example:8080 requests
git config --global http.proxy http://alice:s3cret@proxy.corp.example:8080
Credentials in config files and shell history are a leak risk. Prefer environment variables from a secrets store or an interactive prompt (curl --proxy-user alice prompts for the password).
If the proxy only offers NTLM or Kerberos, run a local forwarding helper (cntlm, px, or a corporate-provided agent), point your tools at http://127.0.0.1:3128, and let the helper authenticate upstream.
If you operate the proxy
Squid with Basic authentication:
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/passwords
auth_param basic realm Corp Proxy
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_access deny all
Two operational traps. First, Proxy-Authorization is a hop-by-hop credential: the proxy must not forward it to the origin. Second, if your proxy does a 407 challenge on a plain HTTP request and your client is an API SDK that does not understand proxy auth, the SDK often surfaces an unhelpful JSON parse error because the 407 body is an HTML page.
407 vs 401 vs 403
| 401 | 407 | 403 | |
|---|---|---|---|
| Issued by | Origin | Proxy | Either |
| Challenge header | WWW-Authenticate | Proxy-Authenticate | none |
| Retry with | Authorization | Proxy-Authorization | credentials will not help |
Related
- 401 Unauthorized: the origin-server version.
- 403 Forbidden
- Proxy-Authenticate and Proxy-Authorization
- Via: shows proxies a request passed through.
- 502 Bad Gateway: what a proxy returns when it can reach no upstream.
Frequently asked questions
What does 407 Proxy Authentication Required mean?
A proxy between you and the destination refused to forward your request until you authenticate to it. The response carries a Proxy-Authenticate header naming the accepted scheme (Basic, NTLM, Negotiate or Digest). The destination server never saw the request.
What is the difference between 401 and 407?
401 comes from the origin server, carries WWW-Authenticate, and is answered with an Authorization header. 407 comes from a proxy, carries Proxy-Authenticate, and is answered with Proxy-Authorization. They can both occur on one request, in that order.
Why does curl say "Received HTTP code 407 from proxy after CONNECT"?
For HTTPS URLs curl first sends a CONNECT request to the proxy to open a tunnel. The proxy demanded credentials on that CONNECT and curl had none, or they were rejected. Add --proxy-user or put credentials in the proxy URL.
My proxy password contains @ or special characters and still fails. Why?
In a proxy URL such as http://user:pass@proxy:8080 the password must be percent-encoded, so @ becomes %40, : becomes %3A and # becomes %23. Unencoded characters make the URL parser split at the wrong place and send the wrong credentials.
How do I fix 407 for pip, npm or git?
Give the tool the proxy URL with credentials through its own setting or the HTTPS_PROXY environment variable: pip --proxy, npm config set proxy and https-proxy, git config http.proxy. If the proxy uses NTLM or Kerberos, a local helper such as cntlm or px is typically needed because these tools only do Basic.
Sources
- MDN Web Docs: 407 Proxy Authentication Requireddeveloper.mozilla.org
- RFC 9110 Section 15.5.8: 407 Proxy Authentication Requiredrfc-editor.org
- RFC 9110 Section 11.7: Proxy-Authenticate and Proxy-Authorizationrfc-editor.org
- curl: proxy optionscurl.se
- Squid: Authentication configurationwiki.squid-cache.org
Related
HTTP CONNECT Method: Proxy Tunnels Explained
HTTP CONNECT opens a TCP tunnel through a proxy so HTTPS can pass untouched. See the exact request and 200 response, 407 proxy auth, and extended CONNECT.
HTTP 401 Unauthorized: Authentication Required
401 Unauthorized means missing or invalid credentials. Read WWW-Authenticate, check the Authorization header, token expiry and proxies, with fixes by stack.
HTTP 403 Forbidden: Access Denied
403 Forbidden means the server refuses the request. Find whether Cloudflare, nginx, Apache, S3 or your app sent it; fix permissions, WAF rules and role checks.
400 Bad Request
400 Bad Request means the server could not parse your request. Find which layer sent it, fix bad JSON and oversized cookies or headers, and reproduce with curl.