Skip to content
RU
← All articles

curl TLS errors 35 and 60: diagnosis and the legacy code 51

In brief:

curl exit 35 indicates a TLS handshake failure; exit 60 indicates certificate verification failed. The current official curl exit-code list has no separate 51. Do not apply an old “51 means hostname mismatch” cheat sheet to a modern binary without checking its version. Read the full error and inspect the name, validity, chain and local trust store.

Engineer examining a TLS connection at a terminal
Start with curl’s exact exit code and error text.

curl still uses “SSL” in some messages for modern TLS. The number alone cannot identify the root cause: an expired certificate, a wrong hostname and an untrusted issuer may all produce 60. A 35 can originate in client options, server policy or an intermediate proxy. Record curl --version and complete stderr first. Cross-check against the official exit codes and libcurl error table.

Capture a reproducible failure

curl --version
curl -vI --connect-timeout 5 --max-time 20 https://example.com/ 2>&1 | tail -40
printf 'exit=%s\n' "${PIPESTATUS[0]}"
# Without a pipeline: curl -sS -o /dev/null https://example.com/; echo "$?"

In bash, use PIPESTATUS[0] after the pipeline or you will report tail’s status. Keep verbose logs private because request headers and URLs may contain secrets. An independent openssl s_client check can reveal the chain and SNI selection.

TLS chain connecting client, certificate and trust store
Code 35 concerns handshake failure; 60 concerns certificate verification.

Separate handshake failures from certificate verification

ExitStageFirst checkPossible causes
35TLS handshakeProtocol version, SNI, proxy and stderrProtocol or cipher mismatch, reset connection
60Certificate verificationName, validity, chain and CA storeExpired certificate, wrong name, untrusted issuer
51Legacy numberingcurl version and its documentationNo separate 51 in the current official list

Our controlled run used curl 8.12.1 with OpenSSL 3.5.8. expired.badssl.com returned 60 with certificate has expired. wrong.host.badssl.com also returned 60, this time for a hostname mismatch. Limiting the client to TLS 1.0 for a request to enterno.io returned 35 and the local message no protocols available. That last result describes this client build; it does not prove the server rejected TLS 1.0.

For a name failure, inspect the certificate SAN and the URL hostname; an IP address is not interchangeable with a DNS name. For a chain failure, compare the served intermediates with the client’s trusted CA roots. The curl certificate guide describes platform-specific trust behavior. A public SSL check is useful, but reproduce a container-specific failure inside that container because CA stores and TLS libraries vary.

Fix the cause instead of disabling verification

For exit 60, renew an expired certificate, correct its SAN or URL, serve missing intermediates, or install the proper trusted root in the client. An internal CA can be passed with --cacert /path/to/ca.pem or installed in the platform trust store. -k/--insecure may isolate a trust failure during diagnosis, but must not remain in production scripts: it prevents the client from authenticating the server.

For 35, check whether your own flags prohibited a usable TLS version. Compare with openssl s_client -connect host:443 -servername host, inspect proxy configuration and read the TLS terminator log. Do not change server ciphers based solely on one number. If only one route fails, compare DNS and proxy paths using the dig guide. The curl timing format helps separate connection setup from response delay.

How we made this guide

We checked the code meanings against current curl documentation. Three failing and one successful request ran from the same environment; version, commands, stderr and exits are preserved in the draft’s data.json. The test endpoints come from BadSSL. This describes one build’s behavior and is not a prevalence survey. SerpAPI and Wordstat informed search wording, not technical conclusions.

FAQ

Why did both certificate failures return 60?

Modern curl can map several verification failures to that exit code. Read the accompanying error text.

What about an old guide that says exit 51?

Check the installed curl version and its documentation. The current official table has no separate 51.

Can -k stay in monitoring?

No. It suppresses trust and name errors that monitoring should detect.

Does 35 always mean the server is broken?

No. A local TLS policy or intermediate proxy can fail the handshake. Inspect both ends.

Sources

Check your website right now

Check your site's SSL →
More articles: SSL/TLS
SSL/TLS
NET::ERR_CERT_AUTHORITY_INVALID: Causes and Exact Fixes
13.07.2026 · 2 650 views
SSL/TLS
SSL Certificate Chain: How to Verify and Fix an Incomplete One
15.04.2026 · 2 131 views
SSL/TLS
SSL Handshake Failed: What Causes It and How to Fix It
15.04.2026 · 2 042 views
SSL/TLS
Russian Trusted Root CA and Sub CA on Servers: Install
15.06.2026 · 1 734 views