Proxy error 407 Proxy Authentication Required: why the proxy rejects your scraper
407 is the one status code you know came from the proxy rather than the site. That narrows the search to four places, and none of them is on the target's side.
What 407 means and how it differs from 403
Status 407 Proxy Authentication Required means the proxy did not accept your credentials. Per the specification such a response must carry a Proxy-Authenticate header naming the authentication scheme the proxy expects, and the client is meant to repeat the request with a Proxy-Authorization header.
The difference from 403 is fundamental. A 403 usually comes from the target site and means “we identified you and refused”; it is addressed with a different address, pauses, headers. A 407 comes from the proxy and means “I do not recognise you”; changing IP or delays does nothing for it. Confusing the two is expensive: people spend weeks tuning delays where a password simply did not match.
Five causes by frequency
- Wrong login and password: a copy-paste typo, or the plan has already expired.
- The machine's IP is not in the whitelist — with IP authentication this looks exactly like a wrong password.
- Protocol mismatch with the port: a SOCKS5 string sent to the HTTP port or the reverse.
- The software does not pass credentials in CONNECT — it only has fields for host and port.
- Special characters in the password are not encoded in the connection string: @, colon and slash break URL parsing.
A one-minute check
The exchange with the proxy happens before any request to the site, so curl's verbose output shows it. That eliminates half the hypotheses immediately.
# -v shows the exchange with the proxy before the request to the site begins
curl -v -x http://LOGIN:PASSWORD@GATEWAY:PORT https://example.com -o /dev/null
# What to look for:
# HTTP/1.1 200 Connection established -> the proxy let you through, 407 is not the issue
# HTTP/1.1 407 Proxy Authentication Required
# Proxy-Authenticate: Basic realm="..." <- the proxy names the scheme
# it expects from the clientIf you see 200 Connection established here but the scraper still gets 407, then the credentials are not reaching the proxy from your code, and the problem is there rather than in the proxy.
Port and protocol — the least visible cause
HTTP and SOCKS5 listen on different ports. A correct login sent to the other protocol's port yields either 407 or a dropped connection with no clear message. Two commands settle it.
# The same login sent to the port of the other protocol returns 407 or drops,
# even though the credentials are correct. Check both:
curl -sI -x http://LOGIN:PASSWORD@GATEWAY:HTTP_PORT https://example.com | head -1
curl -sI -x socks5h://LOGIN:PASSWORD@GATEWAY:SOCKS_PORT https://example.com | head -1When the software cannot pass a password
Some programs and almost every headless browser accept only an address and a port: there is no credentials field, and Chromium additionally ignores credentials passed in the launch argument. In that configuration there is physically nothing to pass a password with.
The answer is IP authentication. The machine's address goes into the whitelist and the proxy recognises the client by the connection itself, without a password. Here both methods are active at once, so nothing needs switching: a server works by whitelist while scripts from a laptop keep using the login.
What is not a cause of 407
- The thread limit: when it is exhausted, connections queue rather than receive 407.
- A block on the site's side: the request has not reached the site yet.
- Exhausted traffic on static plans: that is a different error, not 407.
Telling a proxy refusal from a site refusal
Learn this before changing any settings, because the two cases call for opposite fixes. A property of the protocol helps: over HTTPS the proxy opens a tunnel with a separate command and after that cannot insert anything into the stream. So any response arriving inside HTTPS was produced by the target site.
# A proxy's own response carries service headers. Look for them over
# plaintext http: inside HTTPS the proxy cannot inject anything into the body.
curl -sI -x http://GATEWAY:PORT http://neverssl.com | grep -iE '^via|^server|^x-'
# Typical markers:
# Via: 1.1 squid
# Server: squid/5.7
# X-Squid-Error: ERR_ACCESS_DENIED 0 <- a refusal from the proxy itself
# If those headers are absent and the 403 arrived inside HTTPS, it is the site's.A practical rule follows. A proxy refusal arrives earlier — at the tunnel-establishment stage — and in libraries it surfaces as a proxy error rather than a status code. If you are looking at an ordinary status code inside an HTTPS connection, the site wrote it.
What the browser errors mean
In headless browsers you get a text error identifier instead of a code, and two of them look similar while meaning different stages.
- A tunnel error — you reached the proxy but the tunnel could not be established: no authentication, a forbidden port, an unreachable target host.
- A proxy connection error — the proxy itself is unreachable as a host: the name did not resolve or the socket did not open. The tunnel stage was never reached.
IP and login authentication at the same time
Whitelist for servers and software without credential fields, login and password for everything else. Nothing to switch — both work.
View pricingProxies for this job
Check it with our tools
Read next
- One gateway instead of a proxy list: configuring software that expects a listScrapers measure scale by proxy count, and a rotating gateway is one line. Program by program: which mode to switch, where to duplicate the line, and where the honest answer is to buy a list.
- 403 through a proxy: the site refused, the proxy refused, or the address is not the problemA 403 can come from the proxy or from the target site, and they cannot always be told apart. Where to find the Cloudflare code, which codes no address change will fix, and why proxy headers are a poor test.
- The IP is not changing on rotation: keep-alive is the cause, not the proxyThe exit address is chosen when the connection is established, not when the request is written. Any client with a connection pool holds one IP — the mechanism, plus one-line fixes for requests, httpx and aiohttp.
