Skip to content
RU

curl: (35) SSL Connect Error. Read the Reason and Fix the Handshake

What it means: curl reached the server, but the TLS handshake failed before any HTTP was sent.

  1. Read the reason after the code
  2. Run curl -v and note the last TLS step
  3. Test versions with openssl s_client
  4. Fix protocols, SNI or the middlebox

Test your URL now

Runs a full TLS check: handshake, protocol versions, certificate chain, trust and expiry.

Check your site's SSL →

What curl error 35 means

Exit code 35 is CURLE_SSL_CONNECT_ERROR. The libcurl documentation is blunt about it: «A problem occurred somewhere in the SSL/TLS handshake. You really want the error buffer and read the message there as it pinpoints the problem slightly more.» The code only says «the handshake failed»; the text after it says why.

With the OpenSSL backend that text is OpenSSL's error string, for example TLS connect error: error:0A000410:SSL routines::sslv3 alert handshake failure. When OpenSSL has no reason to give, because the socket simply closed, curl prints OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443 (lib/vtls/openssl.c). On Windows builds using Schannel the text starts with schannel: next InitializeSecurityContext failed: followed by a Windows status.

A rejected certificate is a different exit code. When the handshake completes but the chain or name does not verify, curl returns 60 (CURLE_PEER_FAILED_VERIFICATION) with SSL certificate problem: .... Exit 35 happens earlier: the two sides never agreed on a connection at all.

Reasons and what they point to

Text after the codeWhat happenedTypical fix
sslv3 alert handshake failure (OpenSSL 3.0) or ssl/tls alert handshake failure (3.2+), code 0A000410The server sent a handshake_failure alert: no shared cipher or version, or it needs SNI it did not getConnect by hostname, enable TLS 1.2/1.3 and modern ciphers on the server
tlsv1 alert protocol versionThe server rejects every TLS version the client offeredServer: enable TLS 1.2 and 1.3. Old client: upgrade it
SSL_ERROR_SYSCALL or unexpected eof while readingThe connection was closed or reset during the handshakeLook for a firewall, DPI box, proxy or crashing TLS terminator
wrong version numberThe other end is not speaking TLS on that portUse the right port or scheme; check proxy settings
Schannel revocation statusWindows could not reach the CRL or OCSP serverOpen access to the CA's revocation URLs

The OpenSSL wording changed between releases: OpenSSL 3.0 prints «sslv3 alert handshake failure» while 3.2 and later print «ssl/tls alert handshake failure» for the same reason code 1040 (crypto/err/openssl.txt). Search logs by the hex code 0A000410 to catch both.

Old servers, new clients, and middleboxes

Most error 35 reports after an OS upgrade are version or cipher mismatches. OpenSSL 3 refuses TLS 1.0 and 1.1 at its default security level, so a client that worked against a legacy appliance stops working after the upgrade while browsers were already refusing it. The fix belongs on the server: TLS 1.2 or 1.3 with ECDHE ciphers. As a short diagnostic only, you can check whether an old protocol is the reason by testing it explicitly; do not ship such an override.

When the error appears only on one network (a corporate LAN, a hotel, a CI runner) and the same command works elsewhere, something in the path is interfering: a proxy that resets TLS to hosts it does not like, or a filter keyed on the SNI host name. SSL_ERROR_SYSCALL with zero bytes read is the usual signature. If you must go through an HTTPS-inspecting proxy, configure it with -x rather than letting it intercept transparently.

A server that requires a client certificate also stops TLS 1.2 handshakes with an alert. Under TLS 1.3 curl reports the missing certificate separately, as TLS cert problem: with exit code 58 (CURLE_SSL_CLIENTCERT).

How to fix it

  1. See how far the handshake got. curl -v https://example.com/ prints each TLS step (Client hello, Server hello...). If nothing comes back after the client hello, the server or a middlebox closed the connection.
  2. Check the TLS library curl uses: curl -V shows OpenSSL/3.x, Schannel or another backend. The reason strings differ between them.
  3. Test each version and SNI with OpenSSL:
    openssl s_client -connect example.com:443 -servername example.com -tls1_3 -brief </dev/null
    openssl s_client -connect example.com:443 -servername example.com -tls1_2 -brief </dev/null
    openssl s_client -connect example.com:443 -noservername -brief </dev/null
    If only the last one fails, the server needs SNI and your client is not sending it, typically because it connects to an IP address.
  4. List what the server offers: nmap --script ssl-enum-ciphers -p 443 example.com. No TLS 1.2 or 1.3 entries means the server is the problem.
  5. On your server (nginx): check nginx -T | grep -E 'ssl_protocols|ssl_ciphers' and enable ssl_protocols TLSv1.2 TLSv1.3;. Look in the error log for SSL_do_handshake() failed lines with the same OpenSSL reason.
  6. Schannel revocation failures: make sure the machine can reach the CRL and OCSP URLs in the certificate. --ssl-revoke-best-effort ignores revocation checks only when the distribution points are missing or offline; --ssl-no-revoke turns checks off entirely and loosens security.

How to confirm the fix

curl -sS -o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://example.com/
# 200 0
openssl s_client -connect example.com:443 -servername example.com -brief </dev/null
# Protocol version: TLSv1.3

Test from the network that failed. To see which protocol versions and certificate the server presents from outside, run the SSL/TLS checker.

Related errors

CertificateExpiry, issuer, domains (SAN)
ChainIntermediate and root CA validation
TLS ProtocolTLS version and cipher suite
VulnerabilitiesHeartbleed, POODLE, weak ciphers

Why teams trust us

TLS 1.3
supported
Full
CA chain check
3,158
checks in 30 days
30/14/7
days-to-expiry alerts

How it works

1

Enter domain

2

TLS chain verified

3

Expiry date & vulnerabilities

What Does the SSL Check Cover?

SSL/TLS is the encryption protocol that protects data between the browser and server. Our tool analyzes the certificate, chain of trust, TLS version, and knownvulnerabilities.

Certificate Details

Issuer, validity period, signature algorithm, covered domains (SAN), and validation type (DV/OV/EV).

Chain of Trust

Full chain verification: from leaf certificate through intermediates to root CA.

TLS Analysis

Protocol version (TLS 1.2/1.3), cipher suites, Perfect Forward Secrecy (PFS) support.

Expiry Alerts

Set up a monitor — get Telegram and email alerts 30/14/7 days before expiration.

DV vs OV vs EV Certificates

DV (Domain Validation)
  • Confirms domain ownership only
  • Issued in minutes automatically
  • Free via Let's Encrypt
  • Suitable for most websites
  • Most common certificate type
OV / EV
  • Organization (OV) or Extended Validation (EV)
  • Issued in 1-5 business days
  • Costs $50 to $500/year
  • For finance, e-commerce, government sites
  • Increases user trust

Who uses this

DevOps

SSL certificate monitoring

Security

TLS config audit

SEO

HTTPS as ranking factor

E-commerce

customer trust

Common Mistakes

Expired certificateBrowsers block sites with expired SSL. Set up auto-renewal or monitoring.
Incomplete certificate chainWithout intermediate CA, some browsers and bots cannot verify the certificate.
Mixed content on HTTPS siteHTTP resources on an HTTPS page — the browser lock icon disappears, reducing trust.
Using TLS 1.0/1.1Legacy TLS versions have known vulnerabilities. Use TLS 1.2+ or 1.3.
Domain mismatch in certificateThe certificate must cover all site domains, including www and subdomains.

Best Practices

Set up auto-renewalLet's Encrypt + certbot with cron — certificate renews automatically every 60-90 days.
Enable HSTSStrict-Transport-Security header forces browsers to always use HTTPS.
Use TLS 1.3TLS 1.3 is faster (1-RTT handshake) and safer — legacy ciphers removed.
Monitor expiration datesCreate a monitor on Enterno.io — get notified well before expiration.
Verify chain after renewalAfter certificate renewal, confirm that intermediate certificates are installed.

Get more with a free account

SSL certificate monitoring, check history and alerts 30 days before expiry.

Sign up free

Learn more

Sources

Frequently Asked Questions

What is the difference between curl error 35 and error 60?

Error 35 means the TLS handshake itself failed, so no secure connection was set up. Error 60 means the handshake worked but the server certificate could not be verified.

Does curl -k fix error 35?

No. -k only skips certificate verification, which happens after a successful handshake. A version, cipher or connection problem fails before verification is ever reached.

What does SSL_ERROR_SYSCALL mean in curl?

OpenSSL saw the connection end without a TLS alert, usually a reset or close from a firewall, proxy or a crashing server. Compare the result from another network to find out where it happens.

Why did curl error 35 start after upgrading my OS?

The new OpenSSL refuses old protocol versions and weak ciphers by default. The server still offers only those, so the handshake has no common ground; enable TLS 1.2 or 1.3 on the server.

Why does curl error 35 happen with an IP address but not the hostname?

Connecting by IP sends no SNI, and servers hosting several sites may refuse a handshake without it. Use the hostname, or with curl --resolve example.com:443:203.0.113.10 to pin the IP while keeping the name.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.