Originally published on proxymint.

ERR_TUNNEL_CONNECTION_FAILED means a proxy would not open the HTTPS tunnel. How to see the status Chrome hides, and the fix for each one, in Chrome and code.

TL;DR

  • ERR_TUNNEL_CONNECTION_FAILED is a proxy error, not a website error. Chrome sent an HTTP CONNECT to a proxy to reach an HTTPS site, and the proxy answered with something other than 200, so the site was never contacted.
  • Chrome discards the proxy's reason on purpose. Chromium turns every CONNECT reply except 200 and 407 into error -111 and ignores the body, so a 403 policy block and a 502 from a failed exit look the same.
  • curl and Python print the status Chrome hides. curl -v through the same proxy shows the CONNECT reply line, and Python's error text reads Tunnel connection failed followed by the code.
  • The status points to one fix. 403 is policy, 407 is the login, 405 or 501 is the wrong endpoint, a closed connection is a scheme and port mismatch, and 502, 503 or 504 are failures behind the proxy.

Key takeaways

  • Check chrome://net-internals/#proxy first. It shows whether Chrome uses a fixed proxy, a PAC script or a direct connection, which decides whether to remove a proxy or debug one.
  • Send the same CONNECT with curl -v. The line after the CONNECT request is the proxy's status, and it names the fix in seconds.
  • Use an http:// proxy URL for HTTPS sites. The HTTPS part travels inside the tunnel; an https:// proxy URL asks the proxy port for TLS it usually does not speak.
  • Retry 502, 503 and 504, fail fast on 403, 405, 407 and 501. Configuration errors return the same answer every time, so a retry loop only hides them.
  • Accept curl exit code 7 as well as 56. From curl 8.20.0 a failed CONNECT exits with 7, so scripts that match only 56 miss it.

Read the full guide on proxymint, with the commands, tables and sources.