Evomi

Blog / Error Resolution

Error 407 Proxy Authentication Required: Causes and Fixes

Satyam TripathiSatyam Tripathi21 min read
A mole in a yellow hard hat turns a brass key in a big brass padlock hanging from a red-and-white striped barrier across a cobbled honey-stone lane, beside a red-brick gatehouse with a 407 sign, wisteria and a lantern, with an open wooden toolbox of spanners and a hammer at its feet.

HTTP error 407 Proxy Authentication Required means a proxy refused your request because it didn't get valid credentials. The website never sees that request, so the fix is in your proxy setup.

Many tools don't print the 407 itself. Node's fetch shows only "fetch failed", and Playwright can report a navigation timeout. Java code can also get a 407 with the correct password, because by default the JDK doesn't send it through HTTPS tunnels.

This guide shows how to check whether the credentials or the tool is wrong, then the error message and fix for each tool.

TL;DR

  • Test credentials outside your tool first. One curl request or Evomi's free proxy checker shows whether they work. If so, fix your tool.
  • Evomi's 407 response body separates two causes. "Invalid proxy authorization format" means no usable credentials arrived. "Proxy Authentication Required" means they were wrong.
  • Some tools don't send the password you set. By default, the JDK doesn't send it through HTTPS tunnels. Playwright ignores credentials in the server URL, and %41 in a proxy URL arrives as A.
  • Track 407s separately and stop retrying them. By default, Scrapy sends an HTTPS request 3 times and pip 6 times.

How HTTP error 407 works

RFC 9110 defines 407 as the proxy equivalent of 401. The proxy names the authentication scheme it requires, such as Basic, NTLM, or Negotiate, in a Proxy-Authenticate header. The client then retries with credentials in a Proxy-Authorization header. A website usually returns 401 or 403 for its own login failures.

Sequence diagram with three participants. Your tool sends a request with no credentials to the Proxy. The Proxy answers 407 plus Proxy-Authenticate, drawn in red. Your tool retries with Proxy-Authorization. The Proxy forwards to the Website only if the credentials are accepted

The 407 exchange happens between your tool and the proxy. The website receives the request only after the proxy accepts the credentials.

The error messages below are what each tool prints through Evomi's gateway, with long values shortened to .... A request without credentials gets this response:

Plain Text
HTTP/1.1 407 Proxy Authentication Required
proxy-authenticate: Basic realm=auth
proxy-connection: close
date: Mon, 26 Oct 2026 13:09:42 GMT
content-length: 34
content-type: text/plain; charset=utf-8

Invalid proxy authorization format

The gateway sends the response body "Invalid proxy authorization format" when no usable Basic credentials arrive, such as when the header is missing, the password is empty, or the base64 is invalid. Credentials that arrive but are wrong get the same status code with the body "Proxy Authentication Required". So the first body points to your tool, and the second to your username, password, or port.

Test the credentials outside your tool

One curl request tells you whether the proxy accepts your credentials. Point it at an HTTP site, so that curl prints the proxy's own response instead of a generic CONNECT tunnel error. Take the host and HTTP port from your product's Proxy Generator tab in the dashboard, or from its connection guide for Residential, Mobile, or Datacenter.

Evomi dashboard, Core Residential Proxy Generator tab, showing Username USERNAME, Password PASSWORD, Hostname core-residential.evomi.com and Port 1000 in one outlined line, and the generated string http://core-residential.evomi.com:1000:USERNAME:PASSWORD

The Proxy Generator tab shows the username, password, hostname, and port that work together. The curl command below uses rp.evomi.com, which accepts both Core and Premium Residential credentials, and the hostname your Proxy Generator shows works the same way.

First, put the password in a shell variable for this session. If the password contains a %, type it as %25, because curl percent-decodes the value you pass to -U. The command waits for you to type it and press Enter, shows nothing while you type, and keeps the password out of your shell history:

Shell
read -rs PROXY_PASS

Then send one request. The example uses the Residential endpoint, so change the host and port if you use another product. Replace USERNAME with your proxy username. tail -c 90 keeps only the last 90 bytes, which hold the status code and, for a 407, the whole response body:

Shell
curl -s -w '\n%{http_code}\n' -x http://rp.evomi.com:1000 \
  -U "USERNAME:$PROXY_PASS" http://example.com/ | tail -c 90

A wrong password prints:

Plain Text
Proxy Authentication Required
407

The output tells you what to do next:

Output

Meaning

407 with "Invalid proxy authorization format"

No usable credentials arrived. Check that PROXY_PASS isn't empty and the command has -U

407 with "Proxy Authentication Required"

The credentials arrived, but the username, password, or port is wrong

424 or 400

The credentials work, but a targeting value (424) or a session ID (400) in the password is wrong

200

The credentials work, so fix how your tool sends them

Other proxies may not explain the 407 in the response body. With those proxies, add -v and read the < Proxy-Authenticate: line. If it lists NTLM or Negotiate but not Basic, the proxy won't accept the Basic credentials that -U sends by default. For the fix, see "407 on a corporate or school network" below.

Evomi's free proxy checker tests one proxy or several at once from a web page, so it also works on Windows without the shell commands above. Paste the string from the Proxy Generator as it is, with the http:// prefix, such as http://rp.evomi.com:1000:USERNAME:PASSWORD. If the proxy accepts the credentials, the checker shows the exit IP's location and anonymity level. If it rejects them, it shows "Auth failed", and if the proxy doesn't respond, it shows "Unreachable".

Evomi Free Proxy Checker results table. rp.evomi.com:1000 with credentials shown as USER:PASS has a green dot, 321 ms, Bayonne, United States, a masked exit IP and anonymity Elite. The same host without a login has a red dot and Auth failed, outlined in red. The address 203.0.113.10:8080 has a red dot and Unreachable

With credentials, the checker shows a US exit IP with Elite anonymity. Without them, the checker shows "Auth failed". The exit IP is masked.

Why you're seeing HTTP error 407

Start with the causes you control:

Cause

Who controls it

How to recognize it

The client sent no usable credentials

You

Evomi response body "Invalid proxy authorization format"

Wrong username or password

You

Evomi response body "Proxy Authentication Required"

Credentials from a different product

You

Try them on the host and port of the product they came from

A targeting parameter in the username instead of the password

You

The same credentials work without the parameter

The password was reset, and a worker still has the old one

You

Worked before, fails on some or all workers

Whitespace, \r, or \n at the end of the password

You

Works when typed, fails when read from a secret or .env file

Quotes around the password in a .env file passed to docker run --env-file

You

Works in your shell and in Docker Compose, fails in docker run

% followed by two hex digits in the password

Your HTTP client

Fails only for passwords that contain a %

The proxy accepts only NTLM or Negotiate

IT team

Proxy-Authenticate lists NTLM or Negotiate, but not Basic

The JDK blocks Basic authentication for HTTPS tunnels

Java runtime

HTTP sites work, HTTPS sites return 407

Playwright ignores credentials in the server URL

Playwright

HTTPS navigation times out, and HTTP sites return 407

The username, password, and port of each Evomi product belong together. Copy all three from that product's Proxy Generator tab in the dashboard.

When credentials worked before and fail now, check the credentials each worker receives before you check the code. A changed password may not be deployed to every worker yet. In Kubernetes, a Secret passed as an environment variable doesn't change in a running pod, so restart the pods after a rotation. To compare workers without printing the password, run printf %s "$PROXY_PASS" | sha256sum in each one.

A secret created with echo instead of printf ends in a \n that the proxy reads as part of the password. Recreate it with printf, or remove the trailing newline where your code reads it.

An old copy of the credentials in an environment variable or a tool's config can also override the one you fixed. These commands print the proxy that your shell, npm, git, and pip use, or null or nothing when none is set:

C#
env | grep -i _proxy
npm config get https-proxy
git config --show-origin --get-all http.proxy
pip config list | grep -i proxy

When only some requests get a 407, compare how each worker and each retry builds the proxy URL.

The 407 error message and fix for each tool

The table shows what each tool prints when it sends a wrong password through Evomi's HTTP port, unless a cell says otherwise. For HTTPS sites, the proxy sends the 407 in reply to the client's CONNECT tunnel request. For HTTP sites, it arrives as a normal response, so several tools report no error:

Tool and version

HTTPS site, wrong password

HTTP site, wrong password

curl 7.88.1 to 8.23.0

curl: (7) CONNECT tunnel failed, response 407 on 8.20.0 and later, curl: (56) CONNECT tunnel failed, response 407 on most older builds

Exit code 0, response body printed

curl_cffi 0.17.0 (libcurl 8.23.0)

ConnectionError: Failed to perform, curl: (7) CONNECT tunnel failed, response 407.

Status 407

Python requests 2.34.2

ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 407 Proxy Authentication Required'))

status_code 407, no exception

httpx 0.28.1

httpx.ProxyError: 407 Proxy Authentication Required

Status 407

aiohttp 3.14.5

ClientHttpProxyError: 407, message='Proxy Authentication Required', url='http://USERNAME:PASSWORD@...'

Status 407

Scrapy 2.19.0

TunnelError("Could not open CONNECT tunnel with proxy rp.evomi.com:1000 [{'status': 407, ...}]")

Ignoring response <407 http://...>: HTTP status code is not handled or not allowed, and the spider still finishes

Node.js 24.22.1 and 26.12.1 fetch

TypeError: fetch failed

Same, because fetch uses a CONNECT tunnel for HTTP sites too

axios 1.20.0

AxiosError: Request failed with status code 407

Same

Go 1.27.0 net/http

Get "https://example.com/": Proxy Authentication Required

Status 407

Java 21 to 27 HttpClient

Status 407 with a wrong or a correct password, because the JDK doesn't send the password

HttpClient throws IOException: too many authentication attempts. Limit: 3, and HttpURLConnection returns status 407

Maven 3.10.0

Could not transfer artifact ... from/to central (...): HTTP Status: 407

Maven Central uses HTTPS only

Gradle 9.8.2

Received status code 407 from server: Proxy Authentication Required

Repositories use HTTPS by default

PowerShell 7.6.8 (.NET 10.0.14)

The proxy tunnel request to proxy 'http://rp.evomi.com:1000/' failed with status code '407'

Response status code does not indicate success: 407 (Proxy Authentication Required).

npm 11.12.1 and 12.2.1

npm error code E407

The registry uses HTTPS

pip 26.2.1

ERROR: No matching distribution found for requests

The index uses HTTPS

uv 0.13.5

tunnel error: proxy authorization required

The index uses HTTPS

git 2.55.0

fatal: unable to access '...': CONNECT tunnel failed, response 407

Hosted remotes usually use HTTPS

Playwright 1.64.1 (Chromium)

page.goto: Timeout 30000ms exceeded., the same as with credentials in the server URL

Status 407

Puppeteer 25.16.0 (Chrome 156)

Status 407 with a wrong password, net::ERR_INVALID_AUTH_CREDENTIALS without credentials

Same

Selenium 4.51.0 (Chrome 156)

No password reaches the proxy, so a blank page and no exception. With the BiDi auth handler, TimeoutException

Same blank page and no exception

The Python, Node.js, Java, and Playwright samples below read the credentials from the PROXY_USER and PROXY_PASS environment variables. In the same shell, run read -rs PROXY_PASS if you haven't yet, then export PROXY_USER=USERNAME PROXY_PASS, with your proxy username in place of USERNAME.

curl

The exit code curl returns for a 407 on an HTTPS site changed from 56 to 7 in 8.20.0, and Linux distributions can backport the change. For example, Ubuntu 26.04's curl shows version 8.18.0 but exits with 7. On an HTTP site, curl exits with 0, because the proxy returned a normal HTTP response. So in scripts, don't rely on the exit code. Add -fsS so that any status code of 400 or above fails the command. Also print the proxy's CONNECT status code next to the site's status code to see which one failed:

Shell
curl -fsS -o /dev/null -w 'proxy=%{http_connect} site=%{http_code}\n' \
  -x http://rp.evomi.com:1000 -U "USERNAME:$PROXY_PASS" https://ip.evomi.com/s

A wrong password prints proxy=407 site=000, and a 403 from the website prints proxy=200 site=403. Both fail the command, so read the proxy= value, not the exit code, to see whether the proxy or the website failed.

Evomi's TLS endpoint, https://rp.evomi-proxy.com:1001, encrypts the connection to the gateway, including the proxy credentials. To use it, set -x to that URL, as Evomi's cURL guide shows. Traffic to HTTPS sites is encrypted end to end on either port. The curl proxy authentication guide lists the other flags.

Python

The requests and httpx libraries raise an exception for HTTPS sites but return a normal 407 response for HTTP sites. Call raise_for_status() so that HTTP sites also raise an exception. Percent-encode the credentials before you put them in the URL, as Evomi's Python requests guide also shows:

Python
import os
from urllib.parse import quote

import requests

user = quote(os.environ["PROXY_USER"], safe="")
password = quote(os.environ["PROXY_PASS"], safe="")
proxy = f"http://{user}:{password}@rp.evomi.com:1000"

resp = requests.get(
    "https://ip.evomi.com/s",
    proxies={"http": proxy, "https": proxy},
    timeout=30,
)
# An http:// target returns the 407 as a normal response, not an exception
resp.raise_for_status()
print(resp.text)

To also encrypt the credentials on the way to the gateway, set the proxy URL to Evomi's TLS endpoint, https://rp.evomi-proxy.com:1001. Both requests 2.34.2 and httpx 0.28.1 accept it.

In aiohttp, the ClientHttpProxyError message includes the full proxy URL, with the password, so the password appears in your logs if you log the error. Send the credentials in a Proxy-Authorization header instead. Since version 3.14, aiohttp.BasicAuth, the object behind the older proxy_auth= argument, raises a DeprecationWarning that points to the new helper. Build the header with encode_basic_auth():

Python
import asyncio
import os

import aiohttp

async def main():
    auth = aiohttp.encode_basic_auth(
        os.environ["PROXY_USER"], os.environ["PROXY_PASS"]
    )
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://ip.evomi.com/s",
            proxy="http://rp.evomi.com:1000",
            proxy_headers={"Proxy-Authorization": auth},
        ) as resp:
            print(resp.status, (await resp.text()).strip())

asyncio.run(main())

On aiohttp 3.13 and earlier, use aiohttp.BasicAuth(user, password).encode() instead of encode_basic_auth(). The error for a wrong password then shows only url='http://rp.evomi.com:1000'.

Scrapy

Scrapy reports a 407 for HTTPS sites as a TunnelError in the errback. For HTTP sites, the default HttpErrorMiddleware ignores the 407, and the crawl still ends with finish_reason: finished. To catch both, alert on the downloader/exception_type_count/scrapy.core.downloader.handlers.http11.TunnelError stat for HTTPS sites and the downloader/response_status_count/407 stat for HTTP sites.

Percent-encode the credentials in request.meta["proxy"], because Scrapy decodes them. Evomi's Scrapy guide sets that value for every request in a downloader middleware.

For HTTPS sites, Scrapy retries a failed CONNECT by default, but the retry can't succeed with the same credentials. Remove TunnelError from RETRY_EXCEPTIONS, the list of exceptions that Scrapy retries:

Python
from scrapy.settings.default_settings import RETRY_EXCEPTIONS

custom_settings = {
    # A 407 tunnel failure does not succeed on retry with the same credentials
    "RETRY_EXCEPTIONS": [
        e for e in RETRY_EXCEPTIONS if "TunnelError" not in str(e)
    ],
}

The spider then sends 1 CONNECT request instead of 3. TunnelError is also raised for other CONNECT failures that a retry can fix, so handle those in the errback if you rely on retries for them.

Node.js

In Node's built-in fetch, a 407 appears as fetch failed, and the status code is only in the chain of causes. When fetch uses the proxy in HTTPS_PROXY and the password is wrong, the chain is fetch failed, then Request was cancelled., then Proxy response (407) !== 200 when HTTP Tunneling.

In Node 24 and 26, fetch ignores HTTPS_PROXY unless you set NODE_USE_ENV_PROXY=1 or pass --use-env-proxy. Without them, requests are sent directly from your own IP, with no error. A request to Evomi's IP check page, https://ip.evomi.com/s, shows which IP the site sees. Node 22 has both options from 22.21.0, according to the Node.js CLI docs.

From Node 24.14.0, http.setGlobalProxyFromEnv() in node:http enables the same proxy support in code, without an extra package. With any of these three options, the credentials come from the HTTPS_PROXY URL, so percent-encode them there.

When the proxy or its credentials change per request, use fetch and ProxyAgent from undici, the HTTP client that Node's built-in fetch uses, and log the innermost cause:

JavaScript
import { fetch, ProxyAgent } from "undici";

const credentials = `${process.env.PROXY_USER}:${process.env.PROXY_PASS}`;
const dispatcher = new ProxyAgent({
  uri: "http://rp.evomi.com:1000",
  token: `Basic ${Buffer.from(credentials).toString("base64")}`,
});

function rootCause(err) {
  while (err.cause) err = err.cause;
  return err;
}

try {
  const res = await fetch("https://ip.evomi.com/s", { dispatcher });
  console.log(await res.text());
} catch (err) {
  console.error(rootCause(err).message);
}

Node 24 bundles undici 7, so an undici 8 ProxyAgent passed to the global fetch fails with invalid onRequestStart method. Node 26 bundles undici 8, so the two match there. On either version, import both fetch and ProxyAgent from undici.

In axios 1.20.0, put the credentials in proxy.auth, as Evomi's Node.js guide does. The top-level auth option sets the Authorization header for the website, so the proxy receives no credentials and returns 407.

Java, Maven, and Gradle

The JDK has blocked Basic authentication for CONNECT tunnels by default since Java 8u111. Java 11 and 17 have the same default, and Java 21 to 27 still include jdk.http.auth.tunneling.disabledSchemes=Basic in the JDK's net.properties. With that default, HttpClient and HttpURLConnection return 407 on HTTPS sites even with correct credentials. Set the property to an empty value before the first client is created:

Java
import java.net.*;
import java.net.http.*;

public class Fix {
  public static void main(String[] args) throws Exception {
    // Must run before the first HttpClient is created
    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");

    String user = System.getenv("PROXY_USER");
    char[] pass = System.getenv("PROXY_PASS").toCharArray();
    HttpClient client = HttpClient.newBuilder()
        .proxy(ProxySelector.of(new InetSocketAddress("rp.evomi.com", 1000)))
        .authenticator(new Authenticator() {
          protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(user, pass);
          }
        })
        .build();

    URI target = URI.create("https://ip.evomi.com/s");
    HttpRequest req = HttpRequest.newBuilder(target).build();
    HttpResponse<String> res =
        client.send(req, HttpResponse.BodyHandlers.ofString());
    System.out.println(res.statusCode() + " " + res.body().trim());
  }
}

The program prints 200 and the exit IP. The JDK blocks Basic because Basic sends the password only base64-encoded, not encrypted. Change the property only for proxies you trust.

If you can't change the code, pass -Djdk.http.auth.tunneling.disabledSchemes="" on the command line instead. Clients with their own HTTP stack, such as OkHttp 5.5.1, don't read this setting and work without the change.

Maven 3.10.0 uses its own HTTP client, and so does Gradle 9.8.2 when it resolves dependencies, so this setting doesn't affect them. The Gradle wrapper (./gradlew) downloads Gradle with the JDK client, so that download gets a 407 even with correct credentials. Add systemProp.jdk.http.auth.tunneling.disabledSchemes= to gradle.properties to fix it. Otherwise, a 407 in Maven or Gradle usually means the proxy settings in settings.xml or gradle.properties are wrong.

Playwright, Puppeteer, and Selenium

Playwright 1.64.1 drops any credentials in its server URL and keeps only the protocol, host, and port. The proxy then receives no Proxy-Authorization header, and navigation to an HTTPS site times out. Pass the credentials in the separate username and password fields, as Evomi's Playwright guide also shows:

JavaScript
import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: {
    server: "http://rp.evomi.com:1000",
    username: process.env.PROXY_USER,
    password: process.env.PROXY_PASS,
  },
});
const page = await browser.newPage();
const res = await page.goto("https://ip.evomi.com/s");
console.log(res.status(), (await page.textContent("body")).trim());
await browser.close();

In Puppeteer, credentials inside --proxy-server fail with net::ERR_NO_SUPPORTED_PROXIES, because Chrome rejects them. Pass them with page.authenticate() instead, as Evomi's Puppeteer guide shows. A wrong password there doesn't throw. page.goto() resolves with a 407 response, and the page shows Chrome's "This page isn't working" error, so check res.status() after each navigation.

Chrome error page reading "This page isn't working. If the problem continues, contact the site owner. HTTP ERROR 407" above a Reload button, with the last two lines outlined in red

Chrome 156 shows this page when the proxy rejects the password from page.authenticate(). It says to contact the site owner, but the 407 came from the proxy, so the fix is in your credentials.

With Selenium and Chrome, a reliable fix is a local proxy that stores the credentials and forwards requests to the upstream proxy. The selenium-wire package is archived, and with Selenium 4.51.0 and Chrome 156, the WebDriver BiDi network.add_auth_handler() doesn't respond to the proxy's Proxy-Authenticate challenge. gost 3.3.2 works as that local proxy:

Shell
gost -L http://127.0.0.1:8899 -F "http://USERNAME:$PROXY_PASS@rp.evomi.com:1000"

Start Chrome with --proxy-server=http://127.0.0.1:8899 and no credentials, then check the exit IP at https://ip.evomi.com/s. The same local proxy works for the JDK client and Playwright too. If your password has special characters, percent-encode them in the gost URL. Run gost only on a machine you control, because other local users can see its command line and use its listener.

Some local proxies connect directly to the website when the request to the upstream proxy fails, so the website sees your own IP address. Choose one that blocks the traffic instead, which is called failing closed. The gost setup above fails closed. With wrong credentials, your tool gets a 503 for an HTTP site and a failed connection for an HTTPS site, and the 407 appears only in gost's log.

Use the HTTP port for browsers, because Chromium can't authenticate to SOCKS5 proxies.

A 407 in a Chrome net log from chrome://net-export isn't always a failure. Chromium sends credentials only after the proxy returns a 407 with a Proxy-Authenticate header, so a 407 followed by 200 Connection established is the normal exchange. For HTTPS sites, DevTools doesn't show that first 407, because the CONNECT request to the proxy doesn't appear in its Network panel.

npm, pip, uv, and git

All four tools read the HTTPS_PROXY environment variable. If you export it for a scraper, they also use the proxy when they install packages or clone repositories in the same shell or container, which uses proxy bandwidth. Set it only for the scraper's own command, such as HTTPS_PROXY="http://USERNAME:$PROXY_PASS@rp.evomi.com:1000" python scraper.py. For Node.js fetch, also set NODE_USE_ENV_PROXY=1. If npm, uv, or git shows a 407, check the proxy they read with the config commands under "Why you're seeing HTTP error 407", then fix or unset it.

With pip, the 407 appears only in the retry warnings. Its final error says no matching distribution was found, so the 407 is easy to miss.

Stop retrying a 407 and track it separately

A retry can't fix a wrong password. With default settings, Scrapy sends the same failing HTTPS request 3 times and pip sends it 6 times. With Retry(total=3), urllib3 sends it 4 times.

Treat a 407 as a non-retryable error. Check for a 407 before your retry logic runs. For HTTPS sites, most clients raise a tunnel error instead of returning a status code. The error message differs between clients and versions, so add a test that checks your code detects it.

A 407 is a credential problem, not an outage, so it shouldn't trigger failover. If a crawler retries a 407 request through a fallback proxy, nobody notices the invalid credentials. Alert on the 407 instead.

In monitoring, track 407s as a separate metric from 403s and timeouts. Otherwise invalid credentials appear as a lower success rate that looks like the site is blocking you. Teams may then replace the proxies, even though the status code already shows the cause.

Special characters in proxy passwords

When a password is part of a URL, its special characters must be percent-encoded. In a proxy URL, an unencoded /, #, or ? causes a parse error in curl's -x option, requests, httpx, and aiohttp. An unencoded @ or space works in some clients and fails in others. The requests, httpx, and aiohttp libraries send these characters unchanged, and the proxy accepts the credentials. In curl's -x URL, the same password fails with Unsupported proxy syntax.

A % followed by two hex digits changes the password without any warning, because curl, requests, httpx, and aiohttp all percent-decode it. For example, p%41ss arrives at the proxy as pAss, even with curl's -U option.

Encode the password once, not twice, with quote(password, safe="") in Python or encodeURIComponent() in JavaScript. Evomi's targeting parameters, such as _country-US and _isp-comcast, pass through encoding unchanged.

407 on a corporate or school network

If you never configured a proxy yourself, the 407 usually comes from a proxy on your network, or from a proxy that a VPN app or browser extension set up. Sign in when the browser asks for your username and password, disable any VPN app or proxy extension you installed, and contact IT if the error continues.

Many corporate proxies require NTLM or Negotiate (Kerberos) instead of Basic. The npm and pip clients support only Basic, and from curl 8.20.0, NTLM is off unless the build turns it on, so run curl -V | grep NTLM before you rely on curl or git.

Ask IT for the supported setup, such as a port that accepts Basic or a local NTLM authenticating proxy they approve.

Errors that look like a 407

Each of these errors means the proxy accepted your credentials:

What you see

Cause

Fix

CONNECT tunnel failed, response 424 with "failed to generate properties"

A targeting parameter value that doesn't exist, such as _country-ZZ

Use a valid value, such as _country-US

400 Bad Request about the session ID

A session ID in the wrong format

Use the format in Evomi's proxy sessions docs

401 or 403 with response headers from the site or its CDN, such as cf-ray

The website you requested

Follow the site's own access rules

On a company network, the company's own proxy can also return a 403 when its policy blocks the site. If a 403 has no headers from the site or its CDN, such as cf-ray, it more likely comes from that proxy.

If you can't connect to the proxy at all, see how to fix "cannot establish proxy connection". The most common HTTP proxy errors guide explains the other status codes.

Final thoughts

Before you change any code, test the credentials with the curl command above. If the proxy accepts the credentials and your tool still fails, check Java's jdk.http.auth.tunneling.disabledSchemes property, Playwright's server field, a % in the password, or an outdated proxy environment variable, such as HTTPS_PROXY.

In production, a 407 is a credential problem, so don't retry it and track it separately from 403s and timeouts. On any Evomi product, copy the username, password, and port from the same Proxy Generator tab, and read the 407 response body to see whether credentials arrived. For a new project, start with Evomi's residential proxies.

FAQ

What does 407 mean?

HTTP 407 Proxy Authentication Required means a proxy server refused the request because it didn't receive valid credentials. The website never sees the request. The proxy names the authentication scheme in a Proxy-Authenticate header, and the client can retry with credentials in a Proxy-Authorization header.

How do I fix error 407?

Test credentials outside your tool with one curl request or Evomi's free proxy checker. If they don't work, copy the username, password, and port from your provider's dashboard. If they work, fix your tool's setup. Encode special characters, and in Java, allow Basic for HTTPS tunnels on a trusted proxy.

What does network error 407 mean?

A network error 407 means a proxy on your network asked for a username and password, and your browser or app did not send valid ones. It often comes from a company, school, or VPN proxy. Sign in when asked, disable proxy extensions you installed, or ask your IT team for the correct proxy settings.

How can I fix the HTTP error 407 in Google Chrome?

By default, Chrome uses your operating system's proxy settings, so the 407 comes from the proxy set there or in an extension. Sign in when Chrome asks, check the proxy host and port in system settings, and disable unused proxy extensions. To use an authenticated proxy on purpose, follow Evomi's Chrome proxy guide.