Web and TLS troubleshooting guide
cURL Error 35: SSL_ERROR_SYSCALL Explained
cURL error 35: SSL_ERROR_SYSCALL means cURL could not complete the SSL or TLS connection and OpenSSL associated the failure with the underlying connection or an unexpected peer closure. It is a category of failure, not one universal certificate fix.
Updated August 2026 10 minute read
Analyze your own output
Why Is cURL Failing This HTTPS Request?
Paste cURL error or verbose output. It stays in your browser.
Separate the cURL code from the OpenSSL detail
A typical error looks like this:
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.example.net:443
Code 35 is libcurl's CURLE_SSL_CONNECT_ERROR. It says a problem occurred during the SSL or TLS handshake. The OpenSSL text provides
another layer: SSL_ERROR_SYSCALL indicates that the TLS operation failed around an underlying input or output operation. Older
OpenSSL versions also used this result for some unexpected end-of-file conditions with little additional error-stack detail.
That is why copying a certificate fix from another error 35 case is unreliable. One server may close after the ClientHello because of a policy mismatch, another path may be reset by a firewall, and another request may be speaking TLS to a plain HTTP port.
Capture the last successful stage
Run a controlled verbose request and record the cURL build information:
curl -V
curl -v --connect-timeout 10 --max-time 30 https://api.example.net/ Remove authorization headers, cookies, bearer tokens, client-certificate paths, query secrets, and internal names before sharing the output. Verbose mode can expose request and response headers.
Then identify the last line that completed:
- If the hostname did not resolve, error 35 is not yet the main problem.
- If cURL never reports
Connected, investigate TCP reachability, address family, firewall, and port selection. - If it sends a ClientHello and receives no valid TLS response, focus on the peer, proxy, middlebox, and TLS policy.
- If a ServerHello and certificate appear, the failure is later in negotiation and the detailed alert matters.
Cause 1: the peer or a middlebox closes after ClientHello
A remote server, load balancer, web application firewall, TLS inspection device, or other middlebox can close the connection without returning a useful TLS alert. Compare the same request from another network path and correlate the timestamp with server and edge-device logs. A consistent failure from one source network but not another strongly suggests path policy rather than the certificate chain alone.
Use an independent TLS client with Server Name Indication so the endpoint selects the intended virtual host:
openssl s_client -connect api.example.net:443 \
-servername api.example.net -showcerts
Omitting -servername can produce a different certificate or policy on virtual-hosted infrastructure, making the comparison less
useful.
Cause 2: HTTPS is being sent to the wrong protocol or port
If a TLS client connects to a plain HTTP service, proxy listener, or application protocol port, OpenSSL may report wrong version number,
unexpected bytes, or a generic connection failure. Verify the scheme, host, and port as one unit. Do not assume that every service on port 443 is
correctly configured for TLS or that a custom port speaks HTTPS.
curl -v http://api.example.net:8080/
curl -v https://api.example.net:443/ These are deliberately different requests. Use only the scheme and port that the service documentation specifies.
Cause 3: proxy configuration changes the connection path
cURL can take proxy settings from command-line options, environment variables, and configuration files. An unintended proxy can terminate TLS, create a CONNECT tunnel, resolve the hostname on a different side of the connection, or reject the destination. Check the active environment and repeat with proxy behavior made explicit.
curl -v https://api.example.net/
curl -v --noproxy '*' https://api.example.net/ The second command is a diagnostic comparison only when direct access is permitted. It does not prove that bypassing an organizational proxy is an acceptable production configuration.
Cause 4: client and server TLS policies have no usable overlap
Old servers may support only disabled protocol versions or ciphers. Hardened servers may reject obsolete clients. Some failures return a clear TLS alert, while other devices simply close the connection. Record the cURL version, OpenSSL version, enabled protocols, and server policy. Test a specific protocol version only to identify the compatibility boundary:
curl -v --tlsv1.2 --tls-max 1.2 https://api.example.net/
openssl s_client -tls1_2 -connect api.example.net:443 \
-servername api.example.net Restoring obsolete cryptography globally is not a sound fix. Upgrade the endpoint or client, then keep any temporary exception narrow and documented.
Cause 5: IPv4 and IPv6 follow different paths
A hostname can resolve to both address families while only one path works. Verbose output shows the selected addresses. Compare them directly:
curl -4 -v https://api.example.net/
curl -6 -v https://api.example.net/ If one succeeds and the other fails, inspect DNS records, routing, firewall policy, load-balancer listeners, and certificate deployment for the failing address family. Forcing one family can confirm the difference, but the service should still be corrected for the records it publishes.
Why this is not automatically a certificate-authority problem
Certificate verification failures normally produce more specific messages and commonly map to cURL error 60. A connection that closes before a
certificate arrives cannot be repaired by installing another CA bundle. Likewise, --insecure does not correct a reset, wrong
protocol, failed proxy tunnel, or absent TLS listener.
Do not leave --insecure in scripts. It disables server-identity verification and can hide interception. If a comparison with it changes
the result, investigate the served chain, hostname, trust store, clock, and TLS-inspection policy directly.
A reliable diagnostic sequence
- Record
curl -Vand capture a sanitizedcurl -vfailure. - Confirm the resolved address, selected port, and whether the TCP connection completed.
- Check proxy settings and compare an approved direct path when available.
- Test with
openssl s_clientusing the correct SNI name. - Compare IPv4 and IPv6, then compare another client network.
- Correlate the timestamp with load balancer, WAF, proxy, firewall, and origin logs.
- Change TLS policy only after identifying the exact incompatible stage.
Authoritative references
The libcurl error-code reference defines code 35 as a problem somewhere in the TLS
handshake and recommends using the detailed error buffer. The
OpenSSL SSL_get_error documentation explains
SSL_ERROR_SYSCALL and notes how unexpected EOF reporting changed in OpenSSL 3.0.