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.

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.

Separate handshake failures from certificate verification
| Exit | Stage | First check | Possible causes |
|---|---|---|---|
| 35 | TLS handshake | Protocol version, SNI, proxy and stderr | Protocol or cipher mismatch, reset connection |
| 60 | Certificate verification | Name, validity, chain and CA store | Expired certificate, wrong name, untrusted issuer |
| 51 | Legacy numbering | curl version and its documentation | No 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.