A 407 proxy authentication required response is not usually what people think it is. It is rarely a reply to the request you were trying to make. On any HTTPS address, it is a reply to a different message your client sent first, before your request existed at all.
That is why the advice you have already tried did not work. Retyping the password does not help when the problem is that your client never got to send one, or sent it in a dialect the proxy does not speak.
So: where the challenge actually arrives, what your browser deletes before showing it to you, why a browser sails through while a background app dies silently, and the five causes, with the tells that separate them.
Quick Answer: 407 Proxy Authentication Required
407 Proxy Authentication Required: What It Means, and How It Differs From 401
The proxy authentication required meaning is narrow and it is worth getting exactly right. MDN puts it this way: the status "indicates that the request did not succeed because it lacks valid authentication credentials for the proxy server that sits between the client and the server with access to the requested resource."
Read the second half of that. The party asking is the machine in the middle. The website you wanted has not seen your request, does not know it exists, and is not involved in any way. So what does proxy authentication required mean in practice? Someone you are passing through wants identification, and until they get it nothing moves.
| Code | Who is asking | The header that proves it |
|---|---|---|
| 401 Unauthorized | The website. It wants you to log in to it | WWW-Authenticate |
| 407 Proxy Authentication Required | The proxy in between. The site is not involved | Proxy-Authenticate |
| 403 Forbidden | Someone understood you and refused. Re-authenticating will not change it | Usually none, and no header here is diagnostic |
That middle row is the whole distinction, and it is the one piece of this that every guide does get right. Where they stop is the interesting part: the header does not only tell you who is asking. It names the scheme, and the scheme is what decides whether your software can answer at all.
If the broader picture of which errors belong to your proxy and which belong to the site is unfamiliar, our guide to what a proxy error actually means, layer by layer covers the whole family. This page is the one code on that list that is unambiguously the proxy's.
The Challenge Arrives on the CONNECT, Not on Your Request
Here is the part that reorganizes everything else. When you fetch an http:// URL through a proxy, your client sends the request to the proxy and the proxy answers it. Simple, and the 407 lands where you expect.
When you fetch an https:// URL, none of that happens. Your client first sends a separate message asking for a tunnel, and only once the tunnel exists does your actual request travel inside it, encrypted, where the proxy cannot read it. The proxy challenges that first message. Your request has not been written yet.
The clearest account of this I have found is in curl's own discussion forum, from December 2024, where a user asked why the same failure produced two different results: "When I use curl against a http URL I get error 0 for a 407 response, whereas with a https URL I get error 56 and a 407 response." A contributor's answer: "Usually, to access HTTPS endpoint CONNECT method is used to tunnel any kind of connection through an HTTP proxy", and what you see is "CONNECT tunnel failed, response 407".
That is the origin of the message people paste into search boxes as received http code 407 from proxy after connect. The word CONNECT in it is not a verb. It is the HTTP method your client used, and it is telling you precisely which message was refused.
1 Run it verbosely, with no credentials at all
2 Find the Proxy-Authenticate line in the reply
3 Compare it against plain HTTP
If you are reading this from inside a client rather than a shell, curl's maintainer notes in the same thread that the CONNECT response code is exposed separately, as CURLINFO_HTTP_CONNECTCODE. Two conversations, two results, and one error variable that flattens them.
Our HTTP headers analyzer shows what a server returns to a request unconnected to yours, which is a useful control here. And for where proxies sit and what they may do to a request, our explanation of how a proxy server works in a network covers it.
What Your Browser Deletes Before You See It
If you are chasing this in Chrome, there is something you should know about what actually reaches your screen.
When a proxy answers a tunnel request with a 407, Chromium runs the response through a function called SanitizeProxyAuth before anything else happens to it. That function keeps a list of exactly eight header names and deletes every other header the proxy sent. The list, verbatim from proxy_client_socket.cc:
"transfer-encoding", "upgrade",
"content-length",
"proxy-authenticate"
# everything else the proxy sent is removed
The comment above it explains the intent: "Copy status line and all hop-by-hop headers to preserve keep-alive behavior." The practical effect is that the challenge survives and the proxy's own explanation does not. Any custom header your corporate gateway attached to tell you which policy fired, or which account it did not recognize, is gone before the browser draws anything.
The two error names you may see alongside it are published in Chromium's net_error_list.h, and the difference between them is the most useful thing on this page for anyone on a managed network.
| Error | Chromium's own words | What to do |
|---|---|---|
| ERR_PROXY_AUTH_REQUESTED (-127) | "The proxy requested authentication (for tunnel establishment)" | Normal. Supply credentials, as Section 6 sets out, and move on |
| ERR_PROXY_AUTH_UNSUPPORTED (-115) | "The proxy requested authentication (for tunnel establishment) with an unsupported method" | Your password is irrelevant. The scheme is. Section 4 explains why, Section 6 has the flags |
Note the parenthesis in both: for tunnel establishment. Chromium is saying the same thing curl is. Where Chrome reads its proxy configuration from in the first place is a separate question with a surprising answer, and we took it apart in where Chrome's proxy settings really come from.
Why the Browser Sails Through and Your App Dies Silently
This is the version of the problem that fills bug trackers. The browser on the same machine, on the same network, behind the same proxy, works perfectly. Git, or the installer, or the sync client, fails with a 407 and no prompt and nothing to click.
People conclude their credentials are wrong. They are usually not. Microsoft's own Internet Explorer team documented the mechanism in August 2012, in a post that ranks for none of these searches. It is still the clearest statement of the problem I have found:
The sentence that explains eight years of bug reports
The same post explains why this bites some networks and not others. Where a proxy uses "the NTLM/Kerberos authentication schemes which permit users' Windows logon credentials to be automatically used to respond to challenges from the proxy server", background software authenticates without anyone noticing. Where it uses Basic or Digest, those schemes "require that the user explicitly submit their credentials", and a process with no interface cannot.
One honest caveat: that source is from 2012 and Microsoft has archived it. But the mechanism is architectural rather than versioned, and it still bites. The same complaint has been filed against GitHub Desktop repeatedly since 2018, as recently as April 2025, with matching reports on the Python requests and pip trackers.
There is a second reason an app can fail where a browser succeeds, and it has nothing to do with dialogs: they may not be reading the same proxy configuration at all. On Windows that is close to guaranteed, and we mapped which software reads which store in where Windows actually keeps its proxy settings.
And the number on your screen may not be a 407 at all. Microsoft's sync clients report a code of their own that Microsoft has never published a meaning for, which we took apart in the OneDrive error Microsoft never documented. No source connects that number to HTTP 407 and I will not claim one, but the shape is identical. If your code is not 407 while this section describes your symptoms, read that page too.
The Five Causes, and How to Tell Them Apart
Every guide on this subject gives you a list of causes. The list is not the hard part. Telling them apart is, because every one of them produces the same three digits.
| Cause | The tell | What fixes it |
|---|---|---|
| No credentials were sent | The same command with credentials works immediately | Section 6. Put them where that client reads them |
| Credentials rejected | Correct details fail everywhere, including the browser | Ask the operator. Often an account, not a typo |
| Scheme your client cannot speak | Browser fine, tool fails. ERR_PROXY_AUTH_UNSUPPORTED, or NTLM in the Proxy-Authenticate line | A client that supports it, or ask for Basic over TLS |
| Your IP fell off the allowlist | It worked yesterday and nothing changed. Common on provider proxies | Re-add your current address. Costs nothing |
| Concurrency limit reached | Credentials and address both fine, and it clears when your other jobs finish | Run fewer at once. It is a rate problem wearing a credentials costume |
That last row deserves more attention than it usually gets. Many providers let you authenticate by address instead of by password: you register your public IP and they stop asking. It is convenient right up to the moment your connection gets a different address, at which point the proxy starts demanding a password you may never have been issued.
The last row is the one that catches experienced people, because some providers answer a 407 rather than a 429 when an account exceeds its allowed number of concurrent sessions. It looks exactly like the row above it until you notice it comes and goes.
Of the two, an address that moved is the commoner answer to a 407 that appeared with nothing changed on your side. If you do not know whether your address is fixed or rotating, our guide to checking whether your IP is static or dynamic answers it in a couple of minutes. That is the difference between a one-line fix and a recurring mystery.
Where the Credentials Actually Go
The practical half. Most pages on how to resolve 407 proxy authentication required give you one curl line and stop. Here are the four places credentials live, because the client you are fighting is probably not the one they chose. If the failing program reads the system proxy store instead of any of these, that is the Windows question from Section 4 and the linked guide there is where it is answered.
curl -x http://proxy.example.net:8080 -U username:password https://example.com
curl -x http://proxy.example.net:8080 --proxy-anyauth -U username:password https://example.com
# environment variables, read by most command-line tools
export HTTPS_PROXY="http://username:password@proxy.example.net:8080"
# Python requests
proxies = {'https': 'http://username:password@proxy.example.net:8080'}
# Node. Credentials in the URL are enough, the agent builds the header itself.
new HttpsProxyAgent('http://username:password@proxy.example.net:8080')
# Node, when you must build the value yourself
const creds = Buffer.from('username:password').toString('base64');
new HttpsProxyAgent(url, { headers: { 'Proxy-Authorization': 'Basic ' + creds } })
Use curl's -U rather than credentials in the proxy URL. Both work, but the flag keeps the password out of a string that gets logged and copied into tickets. --proxy-anyauth is documented as picking "a suitable authentication method when communicating with the given HTTP proxy", at the cost of "an extra request/response round-trip". Note it promises a method that works, not the strongest one. When you already know the scheme, use --proxy-basic, --proxy-digest, --proxy-ntlm or --proxy-negotiate.
The requests documentation warns about both of those routes, not just one. Its wording, and note the second half: "Storing sensitive username and password information in an environment variable or a version-controlled file is a security risk and is highly discouraged." A proxies dictionary written into a script you commit is a version-controlled file. The http://user:password@host/ form is the documented way to pass Basic credentials in requests; pulling the password from a secret store at runtime and building the dictionary from that is how you use it without ignoring the warning.
Node is the one most guides skip, and the short form is enough for Basic. The https-proxy-agent package "issues the CONNECT HTTP method, which tells the proxy to open a direct TCP connection to the destination server", and its source injects Proxy-Authorization for you when the proxy URL carries a username or password. The second form, setting the header through the documented headers option, is for when you have to build the value yourself: a token, a rotating credential, a scheme that is not Basic, or a password whose punctuation a URL parser would rewrite. It is also the Node answer to the same objection that makes curl's -U the better habit, since it keeps the secret out of a URL string that gets logged. Either way the header lands on the CONNECT, which is Section 2 made concrete.
Whichever route you take, if the password contains a percent sign, an at sign or a colon, encode it before it goes anywhere near a URL. Otherwise you will spend an evening debugging a password the parser quietly rewrote.
Proxy-Authorization Is Hop-by-Hop, and That Has Consequences
One property of these two headers is documented in the specification, load-bearing, and almost never mentioned. RFC 7235 is explicit about the scope of Proxy-Authorization: it "applies only to the next inbound proxy that demanded authentication using the Proxy-Authenticate field", and "When multiple proxies are used in a chain, the Proxy-Authorization header field is consumed by the first inbound proxy that was expecting to receive credentials."
Consumed, not forwarded. MDN lists both headers among the hop-by-hop set for the same reason. Three consequences follow, and they explain failures that otherwise look random. The first is reassuring, with one condition attached: a conforming proxy consumes the header, so the website does not see your proxy password. The condition is that your client has to stop sending it too, and that is exactly what the third consequence below is about.
In a chain of two proxies, the first consumes the header and the second issues its own challenge. The spec does permit the other behavior, and says so in the same paragraph: "A proxy MAY relay the credentials from the client request to the next proxy if that is the mechanism by which the proxies cooperatively authenticate a given request." May, not must. You cannot assume it, which is why a working setup can break the moment somebody inserts another hop.
And there is a redirect trap, though not for the reason you might guess. Some clients drop Proxy-Authorization across a redirect deliberately. Python requests has done exactly that since version 2.31.0, after CVE-2023-32681 showed the header could leak to the destination server on a redirect to an HTTPS origin. The comment in its own source is blunt about the reasoning: "Avoid appending this to TLS tunneled requests where it may be leaked."
So if you set that header by hand in requests, a redirect strips it and nothing puts it back. Put the credentials in the proxies dictionary instead, built from your secret store rather than typed into the file, and let the library attach them. That is what the fix intends. Otherwise the symptom is a 407 on some URLs and not others, and people go hunting for a per-site rule that does not exist.
When Your 407 Is Not an HTTP 407 at All
A short warning, because it wastes a lot of people's time. SIP, the protocol behind most internet telephony, has its own 407, and it is sent by a SIP proxy about a call or a registration rather than about anything HTTP.
If your 407 arrived from a phone system, a softphone, a PBX or a SIP trunk, nothing on this page applies. There is no browser, no CONNECT, no HTTPS_PROXY variable.
Worth one detail before you go, because it tells you who is actually challenging you. RFC 3261 splits the codes the same way HTTP does: "A proxy uses a 407 (Proxy Authentication Required) response, whereas a UAS or registrar uses a 401 (Unauthorized) response." So a plain registration is normally challenged with a 401. A 407 there means an authenticating proxy is sitting in front of the registrar, and that proxy is who you or your provider needs to look at.
I am flagging it because search engines cannot reliably tell the two apart, so VoIP pages and HTTP pages land in the same results and neither warns you. If telephony is where you are, our explanation of how voice over IP works is the better starting point.
The Short Version
A 407 proxy authentication required response means a machine between you and the site wants identification, and on HTTPS it asks on the CONNECT rather than on your request. Read the Proxy-Authenticate header before you touch a password, because it names the scheme and the scheme decides whether your client can answer at all.
If the browser works and your tool does not, stop suspecting the credentials. Either the tool has no way to prompt you, or it cannot speak the scheme, or it is reading a different proxy configuration entirely. Those are three different fixes and none of them is retyping the password.
And if it started on its own with nothing changed at your end, check whether your address moved. On a provider proxy that is the likeliest explanation, it is free to fix, and it is the one cause that the pages selling those proxies do not mention.
The one thing worth doing before any of it is confirming which address the proxy is actually seeing you from. Our IP trust score checker reports the address you are leaving from and how it is classified, which answers the allowlist question in about ten seconds.