- curl
- Exact text checked with the real tool
curl: (35) … wrong version number
Also seen in: git, PHP, other programs built on libcurl
In one sentence
curl's TLS handshake failed before any certificate check; the text after (35) says why: wrong version number means the other side did not answer with TLS at all.
Where you see it
curl exits with code 35, CURLE_SSL_CONNECT_ERROR: “A problem occurred somewhere in the SSL/TLS handshake” (libcurl error codes). libcurl’s short name for it is “SSL connect error”. The curl command prints the TLS library’s own reason instead, and that reason is what matters:
$ curl https://api.example.com:8080/
curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
Older versions print the same reason in other forms, such as curl: (35) error:0A00010B:SSL routines::wrong version number (curl 7.81) or curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number (OpenSSL 1.1.1). PHP apps show it as cURL error 35.
Text after curl: (35) |
What happened |
|---|---|
wrong version number (packet length too long with most OpenSSL 3.2 to 3.6 releases) |
The other side did not answer with TLS |
tlsv1 alert protocol version |
No TLS version in common |
sslv3 alert handshake failure (ssl/tls alert handshake failure with OpenSSL 3.2 and later) |
No cipher suite in common, or the server wants a client certificate |
tlsv1 alert unknown ca |
The server rejected your client certificate |
SSL_ERROR_SYSCALL or Recv failure: Connection reset by peer |
The connection was closed or reset during the handshake |
Windows schannel: … SEC_E_INVALID_TOKEN, SEC_E_UNSUPPORTED_FUNCTION, SEC_E_ILLEGAL_MESSAGE |
Schannel’s names for the same problems |
What it means
Before curl sends a request over HTTPS, it runs a TLS handshake with the server: they agree on a TLS version and a cipher suite, and the server sends its certificate. Code 35 means this failed before curl got to check the certificate. Certificate problems have their own code, 60, such as unable to get local issuer certificate.
Likely causes
Something other than TLS answers: wrong version number
curl sent a TLS ClientHello and got back something else, usually a plain-HTTP answer. Typical reasons: an https:// URL for a port that speaks plain HTTP, or a proxy URL that starts with https:// for a proxy that speaks plain HTTP.
Confirm: a plain request to the same port works, and your proxy settings show the scheme:
curl -v http://api.example.com:8080/
env | grep -i proxy
$ curl -x https://proxy.example.com:3128 https://example.com/
curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
Fix: use the right scheme or port, for example http:// for the plain service, or the port where the server really speaks TLS. For an ordinary proxy, the proxy URL starts with http:// even for HTTPS traffic: export https_proxy=http://proxy.example.com:3128.
No TLS version or cipher suite in common
The server speaks only old TLS versions, or only cipher suites your curl does not offer. Confirm with OpenSSL:
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_2 </dev/null
openssl s_client -connect api.example.com:443 -servername api.example.com -tls1_3 </dev/null
Fix it on the server: enable TLS 1.2 and 1.3 with modern cipher suites. See How to configure TLS securely and ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
The server wants a client certificate
With mutual TLS over TLS 1.2, a missing client certificate gives alert handshake failure, and one from the wrong CA gives alert unknown ca, both with code 35. Over TLS 1.3 the rejection arrives just after the handshake, as curl: (56) OpenSSL SSL_read: … tlsv13 alert certificate required or … tlsv1 alert unknown ca.
Fix: send the certificate and key the server expects, with the intermediate in the certificate file if there is one:
curl --cert client-chain.pem --key client.key https://api.example.com/
See tlsv1 alert unknown ca and How to set up mutual TLS.
The connection is closed or reset during the handshake
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to api.example.com:443
curl: (35) Recv failure: Connection reset by peer
The other side hung up without a TLS alert. Firewalls and proxies that filter by host name, IP allowlists, overloaded servers and TLS-inspecting devices are typical. Confirm with curl -v from another network, or without the proxy. Fix: ask the network or server owner to allow the connection; see How to work behind a TLS-inspecting corporate proxy, safely.
Check yours
Paste the whole curl line, including the text after (35). The finder shows the page for that reason.
Learn why
- The TLS 1.3 handshake: which messages come first, and where each of these failures happens.
- The same failures elsewhere: ERR_SSL_PROTOCOL_ERROR in Chrome and WRONG_VERSION_NUMBER in Python.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.