curl exit code 35 is CURLE_SSL_CONNECT_ERROR: the TCP connection worked, but the TLS handshake did not finish. The code is a catch-all, so on its own it tells you very little. The text after it, which comes from the TLS library, is where the diagnosis lives. Always read the full line, and run again with -v.
curl -v https://example.com/ 2>&1 | head -n 30
Handshake trouble is different from certificate trouble. If the handshake completes and the certificate is rejected, curl reports exit 60 instead; see curl error 60. If curl never connects, see curl error 7.
Match the message
Text after (35) | Meaning | Go to |
|---|---|---|
SSL connect error (nothing else, older curl/NSS) | Generic, run with -v | Below |
sslv3 alert handshake failure | Server rejected the ClientHello | Handshake failure |
wrong version number | Port is not speaking TLS | Wrong version number |
tlsv1 alert protocol version | No common TLS version | Version section |
Connection reset by peer or SSL_ERROR_SYSCALL | Peer closed during handshake | Reset section |
unexpected eof while reading | Peer dropped the connection without a close | Reset section |
tlsv1 unrecognized name | SNI name not served | SNI section |
Wording differs by curl version and TLS backend (OpenSSL, GnuTLS, Schannel, Secure Transport, NSS), so use the table as a guide to the idea, not an exact match.
Protocol version mismatch
curl -v --tlsv1.2 https://example.com/
curl -v --tlsv1.3 https://example.com/
curl -v --tls-max 1.2 https://example.com/
If --tlsv1.2 works and the default fails (or the reverse), the two sides disagree on versions. An old curl or OpenSSL build cannot do TLS 1.3 and an old server may not do 1.2. The TLS Version Checker shows what the server supports. Upgrade the client if the server is modern; on a server, enable TLS 1.2 and 1.3 rather than going backwards.
Connection reset or unexpected EOF
A reset during the handshake means something actively killed the connection. Candidates:
- A firewall, IPS or WAF dropping handshakes from your IP or fingerprint.
- A load balancer with no TLS listener, or with its backend pool empty.
- A TLS-inspecting proxy that fails on your client's cipher offer.
- A server that crashed or hit a connection limit.
- Rate limiting that triggers on repeated attempts. Wait a few minutes, then try once.
Compare from another network (a phone hotspot is quick) and another client. If it fails everywhere, the problem is server side; if it fails only from one network, the path is blocking it.
openssl s_client -connect example.com:443 -servername example.com </dev/null
curl -v --http1.1 https://example.com/
If openssl s_client also resets, curl is not at fault. Using --http1.1 rules out an ALPN or HTTP/2 negotiation issue; the HTTP/2 and HTTP/3 Checker tests the server's ALPN support.
SNI issues
A name the server does not serve can end in an alert or a default certificate for another site. Make sure you connect by hostname:
curl -v --resolve example.com:443:203.0.113.10 https://example.com/
--resolve pins the IP while keeping the right name in SNI and the Host header. Connecting to https://203.0.113.10/ sends no useful SNI.
Proxy involvement
curl -v prints Uses proxy env variable https_proxy when a proxy is in use. A proxy given as https:// that actually speaks HTTP is a classic source of the wrong version number variant. Test with curl --noproxy '*' ....
Client library problems
- Containers with an old OpenSSL or an incompatible mix of curl and its library produce odd (35) errors. Run
curl -Vand compare with a working host. - On Windows with Schannel, the message text differs (
schannel: ...) and depends on OS-level TLS policy; check the Windows registry-controlled protocol settings or update the OS. - A client certificate (
--cert) with the wrong key or format can fail during handshake. Try without it to isolate.
Do not use -k as a fix
curl -k disables certificate checking only after a successful handshake. It does not repair a handshake failure, so it will not change a (35). If you see it "fix" the issue, you were seeing exit 60 instead.
Verify
After the change, curl -sS -o /dev/null -w "%{http_code} %{ssl_verify_result} %{time_appconnect}\n" https://example.com/ should print a status code, 0, and a nonzero handshake time. Put the endpoint under an uptime monitor to catch policy changes that break clients.
Next steps
- Check the certificate side with the SSL Checker.
- Inspect the presented chain with the SSL Chain Debugger.
- Read about exit code 28 in curl error 28.
- See SSL/TLS certificate errors explained.
FAQ
What does curl 35 mean in plain terms?
The TCP connection opened but the encrypted handshake failed before any HTTP was exchanged.
Is curl 35 the same as curl 60?
No. Exit 35 is a handshake failure, while exit 60 means the handshake worked but the certificate could not be verified.
Why is the message different on my Mac and my server?
They use different TLS backends and curl versions, which phrase errors differently. Check curl -V on each.
Can I fix it with a flag?
Sometimes --tlsv1.2, --tls-max, --ciphers or --http1.1 is a workaround, but the lasting fix is to align client and server settings.
Get notified when this fix updates
Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.
This page is general information written by our editorial team and updated when documentation changes. Servers and providers differ, so test changes safely first. See our editorial policy and disclaimer.