HTTP 407 Proxy Authentication Required — What It Means and How to Fix It
Key takeaways
- 407 comes from the proxy, not the website. A hop in front of you demanded authentication and refused to forward the request. The destination server never saw it.
- 401 is the origin server; 407 is the hop. They use different headers —
WWW-AuthenticateandAuthorizationfor 401,Proxy-AuthenticateandProxy-Authorizationfor 407. Sending the wrong one changes nothing. - Read the
Proxy-Authenticateheader in the response. It names the scheme the proxy expects —Basic,Digest,NTLM,Negotiate— and a client sending Basic to a Digest proxy will 407 forever with perfect credentials. - Credentials placed inside a proxy URL are percent-decoded by most clients, so a password containing
@,:,#,/or%must be URL-encoded or it gets parsed into the wrong field. - Check whether your provider issues one credential pair or two. Some issue separate usernames and passwords for the SOCKS5 port and the HTTP port, and using one on the other's port returns 407 with credentials that are genuinely valid — just not there.
- IP allowlisting and username/password are two different auth modes. If your egress address changed, an allowlist-only setup starts returning 407 with nothing on your side having been edited.
- In a proxy chain,
Proxy-Authorizationis hop-by-hop — the first proxy consumes it and the second never sees it, so the 407 you receive can belong to a hop you did not configure.
HTTP 407 Proxy Authentication Required is one of the least ambiguous errors on the internet: something between you and the destination asked you to identify yourself, and your request did not carry an answer it could use.
What makes it frustrating is that the error looks identical whether your password is wrong, mangled in transit, sent to the wrong port, or never sent at all. Four bugs, one status code. This page separates them.
What a 407 actually is, and who sent it
A 407 is sent by a proxy, not by the website you were trying to reach. The proxy received your request, found no usable credentials for itself, and refused to forward it. The destination server never saw the request at all. It is an authentication challenge for one hop of the path, and it is explicitly temporary.
The defining feature is that the response must carry a Proxy-Authenticate header describing how to authenticate, which your client is expected to answer with Proxy-Authorization:
HTTP/1.1 407 Proxy Authentication Required
Proxy-Authenticate: Basic realm="proxy"
--- your retry ---
Proxy-Authorization: Basic bXl1c2VyOm15cGFzc3dvcmQ=
Everything you need is in the challenge line: the scheme (Basic) and the realm. A client that sends a scheme the proxy never offered will keep collecting 407s with flawless credentials. That Basic value is just base64 of myuser:mypassword — encoding, not encryption, so treat it as a secret.
407 vs 401: the header tells you which one you have
401 means the origin server wants credentials. 407 means an intermediary wants them. They arrive in different headers, are answered by different headers, and a fix aimed at one has no effect on the other. Read the header names rather than pattern-matching on the number.
| HTTP 401 | HTTP 407 | |
|---|---|---|
| Who sent it | The origin server | A proxy between you and the origin |
| Challenge header | WWW-Authenticate | Proxy-Authenticate |
| Header you send back | Authorization | Proxy-Authorization |
| Forwarded upstream? | Yes, end-to-end | No, hop-by-hop and consumed by the proxy |
| Did the site see your request? | Yes | No |
That last row is the useful one: with a 407 the destination has no idea you exist, so its rate limits and bot detection are not yet relevant. By contrast a Cloudflare 1020 is a firewall verdict from the destination's edge, a 429 is a rate limit from something that already accepted you, and a connection that never opens is connection refused, not a status code at all.
Why you get 407 with credentials that look correct
Because valid credentials can still fail to arrive in a usable form. A handful of causes account for most 407s and they all produce an identical response, so work through them in order instead of retyping the password. In every case below, what is on your screen is genuinely correct.
Special characters that were never URL-encoded
Embedding credentials in a proxy URL — http://user:pass@host:port — is how most clients are configured, and most of them percent-decode the userinfo section before use. So a literal @ in the password ends the username early, a literal : splits the fields at the wrong point, a literal % begins an escape sequence, and /, # or ? terminate the authority component outright.
Encode each field separately, never the whole URL at once: @ is %40, : is %3A, # is %23, / is %2F, % is %25. If your client offers a dedicated credentials option instead of the URL, prefer it — those take the value literally and skip the parsing.
One protocol's credentials on another protocol's port
This one is invisible unless you know to look. Some providers issue a single username and password valid on every port. Others issue separate pairs for SOCKS5 and for HTTP, so the two protocols can be rotated and revoked independently.
If your provider is in the second group and you copy the SOCKS5 username onto the HTTP port — or the reverse — you get a 407 with credentials that are real, correctly typed, and simply not valid at the address you sent them to. Nothing in the error hints at it.
Before anything else, check whether your provider issues one credential pair or two, and if two, which pair belongs to the port you are dialling. It is a common cause and it costs ten seconds to rule out.
The credentials never became a header
Some clients accept credentials and then never send them. Chromium-based browsers are the classic case: the --proxy-server flag deliberately ignores any username and password in the URL because the browser expects to prompt a human instead. Headless, nobody answers that dialog, so every request 407s. Automation frameworks work around it with a dedicated authentication call.
The proxy wants a scheme your client is not offering
Basic is the default for most clients and most commercial proxies. Corporate gateways often want Digest, NTLM or Negotiate. A client that only speaks Basic will send Basic, get 407, and stop — correct credentials, wrong language. The Proxy-Authenticate header names what the proxy will accept.
The account is in IP-allowlist mode, not username mode
Most providers support two auth modes: username and password, or an allowlist of source addresses that may connect without credentials. If your account is allowlist-only and your egress address changes — a dynamic ISP lease, a new cloud instance, a VPN toggled on — the proxy stops recognising you and demands credentials you were never issued. Check the allowlist against your current egress address.
HTTPS 407s while plain HTTP works
HTTPS through an HTTP proxy begins with a CONNECT request to open a tunnel, and the proxy authenticates that CONNECT before TLS starts. Clients that attach credentials to ordinary requests but not to CONNECT produce exactly this split. The fix is nearly always configuring both the http and https proxy entries.
Sending proxy credentials correctly
The goal in every client is the same: get a correct Proxy-Authorization header onto both ordinary requests and CONNECT. Below are working shapes in the three clients that generate most 407 reports, each one avoiding the encoding traps above.
curl. Credentials inside -x are percent-decoded; --proxy-user is taken literally and split at the first colon, which makes it safer for awkward passwords.
# Literal — no encoding needed
curl -v --proxy http://proxy.example.com:30001 \
--proxy-user 'myuser:p@ss/w0rd#1' https://api.ipify.org
# SOCKS5 with remote DNS — usually a different port, and on some
# providers a different username and password entirely
curl -v -x 'socks5h://socksuser:[email protected]:30002' \
https://api.ipify.org
Always run with -v: the verbose output shows the CONNECT exchange and the exact Proxy-Authenticate scheme.
Python (requests). Encode each field, set both http and https, reuse a session.
import requests
from urllib.parse import quote
USER, PASS = "myuser", "p@ss/w0rd#1" # exactly as issued, unencoded
proxy = f"http://{quote(USER, safe='')}:{quote(PASS, safe='')}@proxy.example.com:30001"
s = requests.Session()
s.proxies = {"http": proxy, "https": proxy} # both, or CONNECT will 407
print(s.get("https://api.ipify.org", timeout=30).text)
SOCKS5 needs the extra dependency (pip install "requests[socks]") and the socks5h:// scheme, so DNS resolves at the proxy.
Node. Use an agent, and disable the library's own proxy handling so it cannot re-read environment variables and override you.
const { HttpsProxyAgent } = require('https-proxy-agent');
const user = encodeURIComponent('myuser');
const pass = encodeURIComponent('p@ss/w0rd#1');
const agent = new HttpsProxyAgent(`http://${user}:${pass}@proxy.example.com:30001`);
const r = await axios.get('https://api.ipify.org', {
httpAgent: agent, httpsAgent: agent,
proxy: false, // stop axios also applying env-var proxy settings
});
Tools that quietly drop your proxy credentials
A whole category of 407s comes from software that accepted your credentials, said nothing about them, and then did not put them on the wire. When the config looks right and the request disagrees, suspect the tool before you suspect the password.
- Anything reading environment variables.
HTTP_PROXY,HTTPS_PROXY,ALL_PROXYandNO_PROXYare honoured inconsistently, and case matters on some platforms. A tool reading onlyHTTP_PROXYsends HTTPS traffic unauthenticated, or direct. - Frameworks that cache the proxy header separately from the proxy setting. Scraping frameworks commonly strip credentials out of the proxy URL once and reuse the resulting header — change the proxy later and the old header follows the new host.
- Container and daemon-level proxy config. Service proxy settings live in their own files and are not inherited from your shell — a working shell command beside a failing service is normal.
The rule: reproduce with curl -v from the same machine and user before touching application config.
Proxy chains and the 407 you cannot fix
Proxy-Authorization is hop-by-hop. The first proxy that reads it consumes it and does not pass it on. That one rule explains most chain-related 407s, and it explains why adding the second set of credentials to the same request never works.
Picture a laptop in a company network using a commercial proxy: client, corporate gateway, provider proxy, destination. Your request carries one Proxy-Authorization. The gateway takes it. The provider's proxy receives nothing, returns 407, and the gateway relays that 407 to you — a challenge for credentials you know are correct.
Three things make it diagnosable:
- The realm names the challenger. If
Proxy-Authenticatementions a device you did not configure, that is your extra hop. - The same request from an unmanaged network succeeds. A phone hotspot separates "my credentials are wrong" from "something here is intercepting."
- Transparent proxies produce 407s you never asked for. Captive portals and TLS-inspection appliances insert themselves with no config on your side.
The usual fixes: an exception rule on the corporate gateway for the provider's host, or a local forwarder that authenticates outward itself.
When this becomes an infrastructure problem
Nearly every 407 is a configuration bug with a free fix. The case worth naming is the intermittent 407: same config, nobody edited anything, failures clustered in time. That usually means allowlist auth on an egress address that is not stable — a dynamic home lease, an autoscaling pool, a CI runner. The fix is username and password auth.
Keep the credential layer and the address layer separate. A 407 says nothing about the quality of the exit address — and the address is usually why you bought the proxy. Address type interacts with rate limits and reputation scoring; sticky versus rotating interacts with session-based work.
QuantumProxy sits on that second axis — dedicated 4G/5G devices, one tenant per device, and on newer proxies a separate username and password for SOCKS5 and HTTP, which is exactly the setup that produces the protocol-mismatch 407 above. We publish how rotation is verified end to end rather than asking anyone to take it on trust.
The honest limitation: none of this touches the destination. A working proxy with perfect credentials still meets Cloudflare's firewall rules and bot prompts, because those are decided on request behaviour and fingerprints, not on which hop authenticated you. Fixing a 407 gets you to the starting line, not past it — see what is a mobile proxy.
The two-minute diagnostic
Run this before editing anything. It isolates the failure to one layer — network, client, or encoding — faster than reading logs, and it costs two minutes. The point is to compare two requests that differ in exactly one thing, so whatever changes between them is the cause.
Send the same request withcurl -v, using--proxy-userrather than credentials in the URL, first to a plainhttp://target and then to anhttps://one.
Both fail with 407 — read the scheme and realm in the verbose output: the realm names the hop challenging you, the scheme tells you whether your client can answer. HTTP works, HTTPS 407s — your client is not authenticating CONNECT. curl works, your app does not — the credentials are fine and the app is dropping them; see the tools section. --proxy-user works, the URL form does not — encode each field separately.
And if the connection never opens at all — no status line, no headers, just a socket error — you do not have a 407 problem. Start with proxy connection refused instead.
Frequently asked questions
What is the difference between HTTP 401 and HTTP 407?
401 Unauthorized comes from the origin server — the website itself wants credentials, and it asks with a WWW-Authenticate header that you answer with Authorization. 407 Proxy Authentication Required comes from an intermediary between you and that website, and it asks with Proxy-Authenticate, which you answer with Proxy-Authorization. Answering a 407 with an Authorization header does nothing, because the proxy is not reading that field.
Why do I get 407 when my proxy username and password are correct?
The common reasons are that the credentials never reached the proxy as a header, that special characters in the password were not URL-encoded and got parsed into the wrong field, that the proxy expects an auth scheme other than Basic, or that you sent one protocol's credentials to another protocol's port. Each produces an identical 407 with credentials that are genuinely valid.
Does 407 mean I have been blocked or banned?
No. 407 is an authentication challenge, not an access verdict. The proxy is telling you it did not receive usable credentials for this hop. A block from the destination looks different — usually 403, a Cloudflare error page, or a CAPTCHA — and by definition it means your request got past the proxy.
Do I need to URL-encode my proxy password?
Yes, if you are embedding it in a proxy URL. Most HTTP clients percent-decode the userinfo portion of a proxy URL, so a literal @ ends the username early, a literal colon splits the password in the wrong place, and a literal percent sign starts an escape sequence. Encode the username and password separately, or pass them through a dedicated credentials option instead of the URL.
Why does my HTTPS request get 407 when plain HTTP works?
HTTPS through an HTTP proxy uses a CONNECT request to open a tunnel, and the proxy authenticates that CONNECT before any TLS handshake happens. Some clients attach proxy credentials to ordinary requests but not to CONNECT, so plain HTTP succeeds while HTTPS returns 407 from the tunnel setup. Configure both the http and https proxy entries, not just one.
Can a proxy chain cause a 407 I cannot fix?
Yes. Proxy-Authorization is hop-by-hop — the first proxy consumes it and does not pass it on. If your traffic crosses a corporate proxy before reaching your provider's proxy, only one of them can be authenticated from a single header and the other returns 407. The usual fixes are an exception rule on the corporate gateway or a local forwarder that injects the second set of credentials.
Related reading
- Proxy connection refused: causes and how to fix each one
- HTTP 429 Too Many Requests: Retry-After, backoff and rate limit types
- Cloudflare Error 1020 (Access Denied): what actually triggers it
- What is a mobile proxy, and when do you actually need one?
- Dedicated vs rotating proxies: which survives detection?
Dedicated mobile proxies, one dashboard
Real 4G/5G devices on US carrier SIMs. Sticky IP per customer, rotation on demand.
See plans