Save 5% every month: use code 5OFFSTORM at checkout
Home / Guides / ERR_TUNNEL_CONNECTION_FAILED

How to fix ERR_TUNNEL_CONNECTION_FAILED

ERR_TUNNEL_CONNECTION_FAILED means your browser or tool reached the proxy, asked it to open a tunnel to an HTTPS site with a CONNECT request, and the proxy said no or hung up. Run curl -v through the same proxy: the status code the proxy sends back to CONNECT tells you which fix you need.

Updated October 2026Fix proxy errors

Every HTTPS page you load through an HTTP proxy starts with one plain-text request: CONNECT example.com:443. The proxy is supposed to open a TCP connection to that host and answer 200 Connection established. From then on it just passes encrypted bytes back and forth. ERR_TUNNEL_CONNECTION_FAILED (Chromium net error -111) is what Chrome shows when that step fails.

The useful part: the proxy was reachable. If it weren’t, you’d see ERR_PROXY_CONNECTION_FAILED instead. So the problem is in what you asked the proxy to do, whether it was willing to do it for you, or whether the destination answered it.

The same failure has other names outside Chrome: “Tunnel connection failed” in Python, “CONNECT tunnel failed” in cURL, TunnelError in Scrapy. This guide shows how to read the proxy’s answer, then goes through the causes in order of how often they happen.

Which Storm plan fits

Tunnel errors under load usually mean you’re opening more connections than your plan allows. Rotating proxies are sold by threads, so you can size the plan to the number of tunnels your tool really keeps open, with unlimited bandwidth inside them. For long-lived tunnels that must not change IP, a private dedicated proxy fits better than a gateway that rotates.

Rotating proxies (from $14/mo): 700,000+ IPs behind fixed gateway IP:PORTs. New IP on every request, or every 3 or 15 minutes. USA, EU, USA+EU or Worldwide. Unlimited bandwidth on every plan.

Get 40 threads for $39/mo See all rotating 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. Read the proxy’s answer with curl -v

    Run curl -v -x http://GATEWAY_IP:PORT https://the-site.com -o /dev/null. Find the line after > CONNECT. 200 means the tunnel works and the problem is in your tool. 407 is authentication. 502, 503 or 504 means the proxy couldn’t reach the destination. No status and “Connection reset by peer” means the proxy closed the connection without answering; on Storm rotating and residential gateways, that’s what an unauthorized IP looks like.

  2. Use http:// as the proxy scheme

    Storm gateways are plain HTTP proxies that tunnel HTTPS. Write the proxy as http://GATEWAY_IP:PORT even for https sites. An https:// proxy URL makes the client try TLS with the proxy itself, and a socks5:// URL doesn’t work either, because the gateways aren’t SOCKS proxies. Both fail before any tunnel opens.

  3. Check the destination host and port

    With a proxy, DNS for the website is resolved by the proxy, not by your computer. A typo in the hostname or a domain that no longer exists comes back as a tunnel failure, not a DNS error. Also check the port: sending email is blocked on Storm, so tunnels to SMTP ports 25 and 587 fail by design.

  4. Count your open connections

    When you exceed your plan’s threads, new tunnels can fail while old ones keep working. That looks like random failures under load. A browser tab can hold around 10 connections, and a scraper with 50 workers needs 50 threads. Lower concurrency below your limit and test again.

  5. Rule out authorization

    On rotating and residential plans, an unauthorized IP doesn’t get a 407. The gateway accepts the connection and resets it, and browsers report that as a tunnel or proxy connection error. Check that your current public IP is under Authorized IPs in the member area and that 15 minutes have passed since you saved it. A real 407 points to user:pass on a dedicated proxy or another proxy in the chain; see the 407 guide.

  6. Test another destination

    Run the same curl command against a neutral HTTPS site. If that works and one site fails, the destination is refusing or dropping connections from that exit IP, or it’s down. On the Main rotating gateway, the next connection leaves from a different IP, so a retry often succeeds.

  7. Remove interference on your side

    Antivirus HTTPS scanning, corporate proxies and VPN clients can sit between your tool and the gateway and break CONNECT. Test once from a clean network, such as a phone hotspot, with them disabled.

Debug the tunnel step by step

Replace GATEWAY_IP:PORT with a gateway from your member area. The first block shows what a healthy tunnel looks like, so you can compare it with your own output.

A working tunnel in curl -v
$ curl -v -x http://GATEWAY_IP:PORT https://example.com -o /dev/null
*   Trying GATEWAY_IP:PORT...
* Connected to GATEWAY_IP port PORT
* CONNECT tunnel: HTTP/1.1 negotiated
> CONNECT example.com:443 HTTP/1.1
> Host: example.com:443
>
< HTTP/1.1 200 Connection established
* CONNECT phase completed
* TLS handshake ...                       # encryption to the site starts here
< HTTP/2 200
What a failed tunnel looks like
> CONNECT exmaple.com:443 HTTP/1.1         # typo in the hostname
< HTTP/1.1 502 Bad Gateway                  # proxy couldn't reach it
* CONNECT tunnel failed, response 502
curl: (56) CONNECT tunnel failed, response 502

# Other answers you may see after > CONNECT:
#   407 Proxy Authentication Required  -> user:pass wrong, or another proxy
#   503 or 504                         -> destination slow, down or refusing
#   Recv failure: Connection reset     -> IP not authorized (rotating/residential)
#   connection closed, no status       -> thread limit or blocked port
Force a CONNECT tunnel for plain HTTP or other ports
# -p (--proxytunnel) makes curl use CONNECT even for http:// URLs,
# which shows whether a given host:port can be tunnelled at all
curl -v -p -x http://GATEWAY_IP:PORT http://example.com:8080/ -o /dev/null
Python: retry a failed tunnel on a new connection
import time, requests

PROXY = "http://GATEWAY_IP:PORT"            # Main gateway: new IP per connection
proxies = {"http": PROXY, "https": PROXY}

def get(url, tries=3):
    for i in range(tries):
        try:
            # no shared Session: every attempt opens a new tunnel
            return requests.get(url, proxies=proxies, timeout=(10, 30))
        except requests.exceptions.ProxyError as e:
            print("tunnel failed:", e)     # e.g. 'Tunnel connection failed: 502 Bad Gateway'
            time.sleep(2 ** i)
    raise RuntimeError("tunnel failed %d times: %s" % (tries, url))

print(get("https://httpbin.org/ip").json())

How a CONNECT tunnel works

An HTTP proxy can carry HTTPS without seeing inside it. Your client sends CONNECT host:443 HTTP/1.1, the proxy opens a TCP connection to that host, and answers with any 2xx status. RFC 9110 says that after a 2xx, the connection becomes a blind tunnel: the proxy relays bytes until one side closes. Your TLS handshake with the website happens inside it, so the proxy never sees the page, the URL path or your cookies. It only sees the hostname and port.

Chromium treats any other answer to CONNECT (except a 407 it can handle) as a failed tunnel. That includes redirects, which proxies sometimes send to a block page. So ERR_TUNNEL_CONNECTION_FAILED is a catch-all, and the status code behind it is the real diagnosis. You can see it in Chrome with a network log from chrome://net-export, but curl is faster.

Proxy scheme vs website scheme

Most tunnel errors in code come from mixing up two different schemes. The proxy URL’s scheme describes how your client talks to the proxy. The website’s scheme describes what happens inside the tunnel.

  • http://GATEWAY_IP:PORT for the proxy, https://site.com for the target: correct. Plain HTTP to the proxy, CONNECT, then TLS to the site.
  • https://GATEWAY_IP:PORT: the client expects the proxy itself to speak TLS. You’ll get SSL errors such as “wrong version number” or a failed tunnel.
  • socks5://GATEWAY_IP:PORT: Storm gateways aren’t SOCKS proxies, so the handshake fails.

In Chrome, the --proxy-server flag follows the same logic: --proxy-server="http://GATEWAY_IP:PORT". The Python requests and cURL guides show the full setup in code.

Ports, blocked traffic and what tunnels can carry

A tunnel can carry any TCP protocol, not just HTTPS, which is why proxy operators restrict some ports. On Storm, sending email is not allowed and SMTP ports 25 and 587 are blocked, so mail clients and scripts that connect to a mail server through the gateway will always fail. That’s policy, not a fault.

Other ports are about the destination. A site on a non-standard port such as 8443 might simply not answer from outside, and some destinations refuse connections from datacenter ranges. Test the same host on port 443 and a different host on the same port to see which side is refusing.

Tunnels under load and during rotation

Each open tunnel is one thread of your plan for as long as it stays open. Browsers and HTTP clients keep tunnels alive for reuse, so the number in use can be higher than the number of requests you think you’re making. If failures start once you raise concurrency, that’s the limit, and it applies to every machine and tool on the plan together.

The gateways rotate at different points, and that affects long tunnels:

  • Main rotating gateway: the IP is picked when a tunnel opens and stays for that tunnel. A retry on a new connection gets a new IP.
  • 3- and 15-minute gateways: new tunnels get the current IP until it changes.
  • Residential ports: the IP changes every 5 minutes at fixed times (minute 1, 6, 11, 16 and so on). Tunnels open at that moment can drop, so clients that keep connections open for long should reconnect on error. See rotating vs static proxies for when a fixed IP fits better.

Common errors and fixes

Chrome / Edge: ERR_TUNNEL_CONNECTION_FAILEDThe proxy didn’t answer CONNECT with 2xx. Run curl -v through the same gateway to see the status, then follow the matching step above.
Playwright / Puppeteer: net::ERR_TUNNEL_CONNECTION_FAILED at https://...Same Chromium error inside automation. Check the proxy server string starts with http://, that you’re within your thread limit, and that the hostname is right.
Python requests: ProxyError('Unable to connect to proxy', OSError('Tunnel connection failed: 502 Bad Gateway'))The proxy couldn’t reach the destination. Check the hostname and port, test another site, and retry on a new connection. If the code is 407, it’s proxy credentials.
cURL: (56) CONNECT tunnel failed, response 503The destination is down, slow or refusing. Try again later or through a new connection; if every site gives this, check your thread usage.
Scrapy: TunnelError: Could not open CONNECT tunnel with proxyThe error includes the proxy’s status. Lower CONCURRENT_REQUESTS to your thread count, keep the proxy URL on http://, and let the retry middleware try again.
Node.js: tunneling socket could not be established, statusCode=502Same 502 from the proxy. Check the target host; if you use an https:// proxy URL, change it to http://.
Errors only when sending emailExpected: SMTP ports 25 and 587 are blocked on Storm. Send email directly from your server or through your email provider’s API, not through the proxy.

FAQ

What’s the difference between ERR_TUNNEL_CONNECTION_FAILED and ERR_PROXY_CONNECTION_FAILED?

ERR_PROXY_CONNECTION_FAILED means Chrome couldn’t reach the proxy at all. ERR_TUNNEL_CONNECTION_FAILED means it reached the proxy, but the proxy didn’t open the tunnel to the HTTPS site.

Why do only HTTPS sites fail and HTTP sites work?

Plain HTTP requests go through the proxy as normal requests. HTTPS needs a CONNECT tunnel, so anything that blocks CONNECT (a port rule, an unreachable host, an antivirus filter) only hits HTTPS.

Can I send email through Storm proxies?

No. Sending email isn’t allowed, and SMTP ports 25 and 587 are blocked, so tunnels to mail servers on those ports always fail.

Why do tunnels fail only when my scraper runs at full speed?

You’re likely above your plan’s thread limit. New tunnels can fail while the existing ones are busy. Set your worker count at or below your threads, counting every machine that uses the plan.

Should the proxy URL be https:// for HTTPS sites?

No. Use http://GATEWAY_IP:PORT. The site stays encrypted, because TLS runs inside the tunnel between you and the website.

Does clearing Chrome’s cache or flushing DNS help?

Usually not when a proxy is involved, because the proxy resolves the site’s hostname, not your computer. Fix the proxy settings, the hostname or the load instead.

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

Related guides

Tool facts checked against the official documentation (October 2026): Chromium net error list · RFC 9110: CONNECT · MDN: CONNECT · curl man page · Chrome: net-export · Requests docs: Proxies · Scrapy HttpProxyMiddleware. 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.