Save 5% every month: use code 5OFFSTORM at checkout
Home / Guides / 407 Proxy Auth Required

How to fix 407 Proxy Authentication Required

A 407 comes from a proxy, not the website: the proxy wants credentials it didn’t get. On username:password proxies, such as Storm dedicated proxies set to user:pass, the credentials are missing, wrong, badly encoded, or your tool never sent them. Storm rotating and residential gateways don’t answer an unauthorized IP with a 407; they reset the connection. A 407 there points to another proxy in the chain.

Updated October 2026Fix proxy errors

407 Proxy Authentication Required is the proxy’s way of saying “I don’t know who you are.” Your request reached the proxy server, the proxy checked it, and it stopped there. The website you wanted never saw a thing. That’s useful to know, because it means the fix is always between you and the proxy: your credentials, the way your software passes them along, or another proxy sitting in between.

Most 407 errors have boring causes: a password with an @ in it pasted straight into a proxy URL, a password changed in one script but not another, or a tool that silently drops credentials when it opens an HTTPS tunnel. A harder one to spot is a second proxy on your network (a VPN app, an antivirus web shield, a corporate proxy or a browser extension) asking for its own login.

One thing a 407 is not, on Storm: the sign of an unauthorized IP on a rotating or residential plan. Those gateways accept the connection and then reset it, so your tool reports “connection reset”, “Connection aborted” or “socket hang up”. That case is covered below too, because people often search for it under this error.

This guide walks through the checks in the order they usually solve the problem, shows what the error looks like in Chrome, Firefox, Python, cURL, Scrapy and Node.js, and gives working code for each way of sending proxy credentials.

Which Storm plan fits

If your tool keeps fighting credentials (some browsers, Selenium, Java apps), IP authorization removes the problem: rotating and residential plans only use IP authorization, so there is nothing to type. If you need a username and password because your IP changes or the tool runs on several machines, use private dedicated proxies, which accept either method.

Private dedicated proxies (5 for $10/mo): Static USA IPs only you use. IP or user:pass authentication, 100 threads, 1 Gbps network. Unlimited bandwidth on every plan.

Get 5 proxies for $10/mo See all private dedicated proxies plans

Before you start

  1. Log in to the member area and copy your gateway IP:PORTs. They never change; the rotation happens on our side.
  2. Add the public IP of the computer or server that will run your tool under Authorized IPs, click Save, and allow up to 15 minutes before testing. Rotating and residential proxies use IP authentication, so there is no username or password.
  3. Dedicated proxies work with either IP authentication or a username and password. Use user:pass if your IP changes or the tool runs on several machines.
  4. Count your threads: the tool’s total open connections must stay within your plan (for example 40 threads on the 40-thread plan).

Troubleshooting checklist, most likely cause first

  1. Confirm the 407 really comes from your proxy

    Run curl -v -x http://GATEWAY_IP:PORT https://example.com. If the 407 appears right after the CONNECT line, it’s your proxy speaking. Look for a Proxy-Authenticate header in that response: it names the scheme the proxy wants (usually Basic). If curl works but your app fails, the problem is in the app’s settings, not the proxy.

  2. Rotating or residential: a reset is the IP symptom, not a 407

    Storm rotating and residential gateways don’t send a 407 to an unauthorized IP. They accept the TCP connection and reset it. If you get a reset, open a “what is my IP” page without the proxy and compare the IPv4 address with the list under Authorized IPs in the member area. Home connections get new IPs after router restarts, and a VPN gives you a different one. Save the right IP and wait up to 15 minutes before you test again. If you see a real 407 while using only these gateways, another proxy is asking: go to step 6.

  3. User:pass proxies: re-copy the credentials

    Copy the username and password again from the member area instead of typing them. Watch for a trailing space, a swapped 0/O, or a password you changed and forgot to update in one script. Credentials are case-sensitive.

  4. URL-encode special characters

    If the credentials sit inside a proxy URL (http://user:pass@PROXY_IP:PORT), characters such as @, :, /, #, % and ? break the URL. Encode them (@ becomes %40) or pass the credentials in a separate field such as curl’s --proxy-user.

  5. Make sure the tool sends credentials for HTTPS too

    Some tools send credentials on plain HTTP requests but not on the CONNECT request that opens an HTTPS tunnel. Chrome’s --proxy-server flag ignores a user:pass in the URL, and Java disables Basic auth for tunnels by default. If HTTP sites load and HTTPS sites return 407, this is your cause.

  6. Look for a second proxy in the chain

    Corporate networks, antivirus “web shields”, some VPN apps and browser proxy extensions run their own proxy. Their 407 has nothing to do with your proxy account. Check the HTTP_PROXY and HTTPS_PROXY environment variables and your system proxy settings, and test once from a network without them.

  7. Switch the authentication method if the tool can’t cooperate

    If a tool has no reliable way to send proxy credentials, stop fighting it. Authorize your machine’s IP instead: rotating and residential plans work that way by default, and dedicated proxies can use IP authorization too.

Send proxy credentials correctly

Rotating and residential gateways need no credentials once your IP is authorized, so the plain GATEWAY_IP:PORT form is enough. The user:pass examples apply to private dedicated proxies set to username and password authentication.

cURL: see who sends the 407
# IP-authorized gateway (no credentials)
curl -v -x http://GATEWAY_IP:PORT https://example.com -o /dev/null

# Dedicated proxy with username and password, kept out of the URL
curl -v -x http://PROXY_IP:PORT --proxy-user 'USERNAME:PASSWORD' https://example.com -o /dev/null

# A real 407 in the -v output looks like:
#   > CONNECT example.com:443 HTTP/1.1
#   < HTTP/1.1 407 Proxy Authentication Required
#   < Proxy-Authenticate: Basic realm="..."

# Storm rotating/residential gateway, IP not authorized (no 407):
#   * Connected to GATEWAY_IP (GATEWAY_IP) port PORT
#   * Recv failure: Connection reset by peer
URL-encode a password (Python)
from urllib.parse import quote

password = "p@ss:w/rd#1"
print(quote(password, safe=""))     # p%40ss%3Aw%2Frd%231
# Proxy URL: http://USERNAME:p%40ss%3Aw%2Frd%231@PROXY_IP:PORT
Python requests with credentials
import requests
from urllib.parse import quote

user, pwd = quote("USERNAME", safe=""), quote("PASSWORD", safe="")
proxy = f"http://{user}:{pwd}@PROXY_IP:PORT"
r = requests.get("https://httpbin.org/ip",
                 proxies={"http": proxy, "https": proxy}, timeout=20)
print(r.status_code, r.text)
Scrapy: credentials in request.meta
# Scrapy's HttpProxyMiddleware turns user:pass in the proxy URL
# into a Proxy-Authorization header, also for HTTPS tunnels.
yield scrapy.Request(
    url,
    meta={"proxy": "http://USERNAME:PASSWORD@PROXY_IP:PORT"},
)
Playwright and Puppeteer (Node.js)
// Playwright: credentials go in their own fields
const browser = await chromium.launch({
  proxy: { server: "http://PROXY_IP:PORT", username: "USERNAME", password: "PASSWORD" },
});

// Puppeteer: --proxy-server takes no credentials; answer the 407 with authenticate()
const browser2 = await puppeteer.launch({ args: ["--proxy-server=http://PROXY_IP:PORT"] });
const page = await browser2.newPage();
await page.authenticate({ username: "USERNAME", password: "PASSWORD" });
Java: allow Basic auth for HTTPS tunnels
# Since JDK 8u111, Basic auth is disabled for CONNECT tunnels by default.
# Re-enable it when you start the app:
java -Djdk.http.auth.tunneling.disabledSchemes="" -jar your-app.jar

What a 407 actually says

RFC 9110, the HTTP standard, defines 407 as the proxy version of 401: the client has to authenticate itself to use the proxy. A proxy that answers 407 must include a Proxy-Authenticate header naming the scheme it accepts. The client then repeats the request with a Proxy-Authorization header carrying the credentials, usually Basic followed by the base64 form of user:pass.

Two details explain a lot of confusing cases:

  • Proxy-Authorization is meant for the first proxy only. It isn’t passed on to the website. If you chain two proxies, each one needs its own credentials, and the 407 you see might be from either.
  • For HTTPS sites the 407 arrives before encryption starts. Your client sends CONNECT host:443 to the proxy in plain text, and the proxy refuses that request. This is why some libraries report it as a tunnel or connection error rather than an HTTP status code.

Compare it with its neighbours: 401 means the website wants a login, 403 means the website (or proxy) knows the request and refuses it anyway, and 407 means the proxy wants to know who you are before it does anything.

IP authorization vs username and password

Proxies identify you in one of two ways, and a rejection looks different in each case.

IP authorization (all rotating and residential plans, optional on dedicated): the gateway checks the source IP of your connection against the list you saved in the member area. There are no credentials to get wrong, so a rejection means the IP doesn’t match. On Storm rotating and residential gateways that rejection isn’t a 407: the gateway accepts the connection and resets it. Python requests shows a ProxyError with ConnectionResetError or RemoteDisconnected, Node shows ECONNRESET or “socket hang up”, curl shows “Recv failure: Connection reset by peer”. The usual reasons:

  • Your home IP changed after a router restart or ISP renewal. If that happens often, authorize a free dynamic DNS hostname (No-IP) instead of a raw IP.
  • You authorized an IPv6 address. Many “what is my IP” sites show IPv6 first, but a connection to an IPv4 gateway leaves from your IPv4 address. Authorize that one.
  • A VPN is on, so your traffic reaches the gateway from the VPN’s IP.
  • The script runs somewhere else: a server, a CI runner, a hosted notebook or a tool’s own cloud. Authorize that machine’s IP, and if it changes on every run, move the job to a VPS with a fixed IP or use dedicated proxies with user:pass.
  • You saved the IP less than 15 minutes ago.

Username and password (dedicated proxies set to user:pass): the proxy checks the Proxy-Authorization header. This is where a 407 belongs. It means the header was missing, malformed or wrong. Everything in steps 3 to 5 above applies.

The IP authentication guide covers whitelisting in more detail.

Special characters break proxy URLs

A proxy URL is parsed like any other URL, so reserved characters in a password change its meaning. In http://bob:pa@ss@PROXY_IP:PORT, the parser sees the first @ as the end of the credentials, sends pa as the password and tries to connect to a host called ss@PROXY_IP. Depending on the library you get a 407, a DNS error, or a confusing “invalid port” message.

Encode these characters before you put them in a URL:

  • @ → %40, : → %3A, / → %2F
  • # → %23, ? → %3F, % → %25
  • a space → %20

Shell users have a second trap: $ and ! in a password inside double quotes get expanded by bash and zsh. Wrap credentials in single quotes on the command line, or keep them in an environment variable.

Tools that drop credentials on HTTPS tunnels

“HTTP works, HTTPS gives 407” almost always means credentials aren’t sent with the CONNECT request. Known cases:

  • Chrome and Chromium flags. --proxy-server=http://user:pass@host:port ignores the credentials. Chrome shows a sign-in dialog in a normal window and fails in headless mode. Puppeteer’s page.authenticate() and Playwright’s username/password fields answer the challenge for you; with Selenium, IP authorization is the simplest route (see the Selenium guide).
  • Java. The JDK property jdk.http.auth.tunneling.disabledSchemes lists Basic by default, so HttpURLConnection won’t send Basic credentials when tunnelling. Set it to an empty string at startup.
  • Desktop apps using system proxy settings. Windows and macOS proxy settings have no reliable place for a password, so many apps never send one. Use IP authorization for these.

Fixing 407 in a browser

Chrome uses your operating system’s proxy settings (see the Chrome proxy guide). When a user:pass proxy answers 407, Chrome opens a “Sign in” dialog naming the proxy. Enter the credentials there; Chrome remembers them for the session. Firefox has its own proxy settings and shows an “Authentication Required” prompt for the proxy.

If the dialog keeps coming back, the credentials are wrong. On a Storm rotating or residential gateway you shouldn’t see this dialog at all: an unauthorized IP there ends in a proxy or tunnel connection error, not a sign-in prompt. If a prompt appears anyway, a different proxy is asking, such as a system proxy, VPN, corporate proxy or extension. Check which proxy the browser really uses.

Common errors and fixes

Chrome: “Sign in. Proxy http://IP:PORT requires a username and password”The proxy answered 407. Enter dedicated-proxy credentials. If you only use Storm rotating or residential gateways, the prompt comes from another proxy in the chain (system proxy, VPN, extension). In headless Chrome this shows up as a failed load instead.
Firefox: “The proxy moz-proxy://IP:PORT is requesting a username and password”Same 407, Firefox wording. Check the credentials; if they’re right and the prompt repeats, the password may have special characters Firefox can’t send as typed, or the prompt comes from a different proxy than the one you set.
Python requests: ProxyError(... 'Tunnel connection failed: 407 Proxy Authentication Required')The CONNECT for an HTTPS URL was refused. Encode the password with quote(), and set both http and https keys. For plain HTTP URLs you get a normal response with status_code == 407 instead.
cURL: (56) CONNECT tunnel failed, response 407Older curl versions print Received HTTP code 407 from proxy after CONNECT. Pass credentials with --proxy-user 'user:pass' in single quotes, and check for a second proxy in HTTPS_PROXY.
Storm rotating/residential: Connection reset by peer or Connection aborted, no 407Not a 407 at all. The gateway accepted the connection and reset it because your current IP isn’t authorized. Add your public IPv4 under Authorized IPs, click Save and wait up to 15 minutes.
Scrapy: TunnelError: Could not open CONNECT tunnel with proxy ... 'status': 407Put credentials in meta['proxy'] as http://user:pass@host:port, URL-encoded.
Node.js axios: Request failed with status code 407Set proxy.auth with username and password, or use an agent such as https-proxy-agent with credentials in the URL.
Java: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407"Basic auth for tunnels is disabled by default. Start the JVM with -Djdk.http.auth.tunneling.disabledSchemes="" and set an Authenticator.

FAQ

Is a 407 error the website blocking me?

No. The request never got past the proxy, so the website didn’t see it. A block by the website looks like a 403, a 429 or a CAPTCHA page.

Do Storm rotating proxies need a username and password?

No. Rotating and residential plans use IP authorization only. Add your public IPv4 under Authorized IPs in the member area, click Save, wait up to 15 minutes, and use http://GATEWAY_IP:PORT with no credentials.

What does an unauthorized IP look like on Storm rotating proxies?

A reset connection, not a 407. The gateway accepts the TCP connection and then closes it, so you see “Connection reset by peer”, “Connection aborted”, ECONNRESET or a browser tunnel error. “Connection refused” is different: it means nothing answered on that IP and port, usually a typo or a firewall.

I added my IP to Storm but the connection still resets. Why?

Usually one of three things: less than 15 minutes have passed, you saved your IPv6 address instead of IPv4, or the tool runs on a different machine (or behind a VPN) than the one whose IP you saved. Check the IP from the machine that actually runs the tool.

Can I use username and password with Storm proxies?

Yes, on private dedicated proxies, which support either IP or user:pass authentication. Rotating and residential plans don’t offer user:pass.

Why does HTTP work but HTTPS returns 407?

Your tool sends credentials on normal requests but not on the CONNECT request that opens the HTTPS tunnel. Chrome’s proxy flag and Java’s default settings are the usual suspects. Switch to a method that answers the proxy challenge, or use IP authorization.

Still have questions? Contact us here. A real person answers.

Related guides

Tool facts checked against the official documentation (October 2026): RFC 9110: 407 Proxy Authentication Required · RFC 9110: Proxy-Authenticate · MDN: 407 Proxy Authentication Required · curl man page · Requests docs: Proxies · Scrapy HttpProxyMiddleware · Puppeteer page.authenticate · Playwright: HTTP proxy · Java networking properties · Chromium net error list. Storm Proxies facts: our plans page and refund policy.

Unlimited bandwidth. One flat monthly price.

Access is live the moment you pay, and the smallest package of each proxy type has a 24-hour money-back guarantee on your first order.