Skip to content
Troubleshooting

cURL Proxy Errors Explained: Exit Codes 5, 7, 28, 35, 56 and 97

When cURL fails through a proxy, the exit code tells you which leg of the connection broke. Codes 5 and 7 mean cURL never reached the proxy. Code 56 with “CONNECT tunnel failed” means the proxy was reached and refused the tunnel, and the HTTP status it prints — 407, 403, 502 — names the reason. Code 97 is a SOCKS handshake failure, and 35 is a TLS problem, usually with the proxy scheme rather than the website.

seamless Team10 min readSeptember 28, 2026
  • troubleshooting
  • curl
  • command line
  • proxy errors
A compact terminal block sending one straight crimson line through a ring-shaped relay toward a distant slab

This page is for when the command fails. For the working syntax — flags, SOCKS5, geo checks — see the cURL integration page.

Start with verbose output

bash
curl -v -x http://USERNAME:PASSWORD@PROXY_HOST:PROXY_PORT https://example.com -o /dev/null

# Typical healthy output:
# * Connected to PROXY_HOST (203.0.113.10) port PROXY_PORT
# * CONNECT tunnel: HTTP/1.1 negotiated
# > CONNECT example.com:443 HTTP/1.1
# < HTTP/1.1 200 Connection established
# * CONNECT phase completed
Connected means leg one worked. The status line after CONNECT is leg two.

Read the output top to bottom and stop at the first line that is not what you expected. That line is the problem; everything after it is consequence.

Exit codes at a glance

Exit codeMessageLegMost likely cause
5Could not resolve proxy1Typo in the proxy hostname, or DNS unavailable
6Could not resolve host2Target hostname wrong, or socks5:// resolving locally
7Failed to connect1Wrong port, dead proxy, or local firewall
28Operation timed out1 or 2Silent firewall drop, or a slow exit
35SSL connect error1 or 2https:// proxy scheme on a plain HTTP proxy
52Empty reply from server1Wrong protocol for that port
56CONNECT tunnel failed, response NNN2The proxy refused — read NNN
60SSL certificate problem2Intercepting proxy or corporate TLS inspection
97Proxy handshake error1SOCKS authentication or version mismatch

curl: (5) Could not resolve proxy

cURL could not turn the proxy hostname into an address. Check the spelling, then run nslookup PROXY_HOST. If a stray environment variable is pointing cURL at an old proxy you forgot about, -v shows its name here — see the section on environment variables below.

curl: (7) Failed to connect to proxy

  • Connection refused arrives instantly: something answered and said nothing is listening. Almost always the wrong port — HTTP and SOCKS5 endpoints often use different ones.
  • A hang, then code 7 or 28, means nothing answered at all. A firewall is dropping the packets silently; test from another network such as a phone hotspot.
  • Expired or exhausted plans can close the port rather than return an error, so check the dashboard before debugging your network.

Use --connect-timeout 10 when testing. Without it, a firewalled proxy can make cURL wait for minutes before reporting anything, and you will assume the proxy is slow rather than unreachable.

curl: (56) CONNECT tunnel failed

This is the most common proxy error and the most informative, because it quotes the proxy's answer. The number at the end of the message is an HTTP status from the proxy, not from the website.

ResponseMeaningFix
407Proxy authentication requiredSend credentials with -U or in the proxy URL; URL-encode special characters. See 407 errors
403Proxy refuses this destinationTest a neutral site; the proxy may filter that host or port
405Tunnelling not allowedThe endpoint does not support CONNECT — wrong product or port
502Proxy could not reach the targetRetry on a new exit or session
503Proxy temporarily unavailableBack off and retry; check provider status
bash
# A password containing @ or : must be encoded in the URL
curl -x "http://USERNAME:p%40ss%3Aword@PROXY_HOST:PROXY_PORT" https://example.com

# Or pass it separately, where no encoding is needed
curl -x http://PROXY_HOST:PROXY_PORT -U "USERNAME:p@ss:word" https://example.com
An unencoded @ splits the URL in the wrong place and turns into a 407 with the right password.

Remember the flag distinction: -U / --proxy-user authenticates to the proxy, while -u / --user authenticates to the website. Credentials passed with -u never reach the proxy, which then answers 407 no matter how correct they are.

curl: (35) SSL connect error

Usually the proxy URL starts with https:// when the proxy speaks plain HTTP. cURL tries to open TLS to the proxy itself, the proxy replies in plaintext, and the handshake fails. For almost every proxy product the right scheme is http://, even for HTTPS targets — the target's TLS runs inside the tunnel. Only use https:// for a proxy that explicitly supports TLS on the proxy hop.

curl: (97) Proxy handshake error

A SOCKS negotiation failed before any data moved. Check that the endpoint really is SOCKS5 rather than HTTP, that the port is the SOCKS port, and that the credentials are right — SOCKS5 password authentication fails here rather than with a 407. Prefer socks5h:// so the proxy resolves the hostname; plain socks5:// resolves it on your machine, which can also produce code 6 for hosts only the proxy can resolve.

bash
curl -v -x socks5h://USERNAME:PASSWORD@PROXY_HOST:SOCKS_PORT https://api.ipify.org

HTTP and SOCKS5 on every plan

Residential from €1.20/GB and ISP from €1.80/IP, with username or IP-whitelist authentication. Test with one cURL command before you write any code.

See pricing

Environment variables that override you

cURL reads proxy settings from the environment, and a forgotten variable is a classic source of errors that seem to ignore your flags.

  • `http_proxy` is only read in lowercase. HTTP_PROXY is ignored on purpose, for CGI security reasons.
  • `HTTPS_PROXY` / https_proxy covers HTTPS targets; `ALL_PROXY` applies to everything else.
  • `NO_PROXY` lists hosts that bypass the proxy — handy for internal services, confusing when a target is on it by accident.
  • `-x` on the command line always wins. --noproxy '*' disables the proxy entirely for one call, which is the quickest way to prove whether the proxy is involved at all.

Windows: curl vs curl.exe

In Windows PowerShell 5.1, curl is an alias for Invoke-WebRequest, which does not understand -x, -U or -v and fails with a parameter error that looks nothing like a proxy problem. Type curl.exe to use the real cURL that ships with Windows 10 and 11. PowerShell 7 removed the alias, but curl.exe works everywhere and saves the question.

Proxy works in cURL but not in your app

Then the proxy is fine and the difference is in the client. The usual suspects are a library that does not send credentials on CONNECT, a headless browser that drops them — see ERR_TUNNEL_CONNECTION_FAILED — or an https:// scheme in a config file. Compare the exact proxy URL the application uses with the one that worked here, character by character.

Sources

Frequently asked questions

What does curl: (56) CONNECT tunnel failed mean?

cURL reached the proxy and asked it to open a tunnel to the target, and the proxy refused. The number at the end is the proxy's HTTP status: 407 means authentication is missing or wrong, 403 means that destination is not allowed, and 502 means the proxy could not reach the target.

What does curl: (7) Failed to connect to proxy mean?

cURL could not open a TCP connection to the proxy. An immediate refusal usually means the wrong port; a long hang means a firewall is dropping the connection. The proxy was never reached, so credentials are not the issue.

What is the difference between -U and -u in cURL?

-U or --proxy-user sends credentials to the proxy. -u or --user sends credentials to the destination website. Using -u for proxy credentials results in a 407 error from the proxy.

Should I use http:// or https:// for the proxy in cURL?

Use http:// for almost every proxy, including when the target is HTTPS. The target's TLS runs inside the CONNECT tunnel. https:// tells cURL to use TLS to the proxy itself, which only works if the proxy supports it and otherwise fails with exit code 35.

What is curl error 97?

Exit code 97 is a proxy handshake error, most often a failed SOCKS negotiation: wrong port, an HTTP endpoint addressed as SOCKS, or rejected SOCKS5 credentials.

Why does curl ignore my HTTP_PROXY variable?

cURL only reads the lowercase http_proxy variable for plain HTTP targets. The uppercase form is deliberately ignored. HTTPS_PROXY, ALL_PROXY and NO_PROXY are accepted in either case.

SE
seamless Team
Proxy infrastructure

The seamless team runs residential, ISP and datacenter proxy infrastructure and writes these guides from day-to-day operational experience.

Ready to try seamless proxies?

Residential, ISP and datacenter proxies with no data expiry.

Browse Plans