curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
appeared here when an https:// URL pointed at a port where a plain HTTP server
listened. Use http:// for that port, or send https:// to the port
where a TLS server listens.
The fix is a matter of matching the scheme to the port. In this test, port 8080 spoke plain HTTP and port 8443 spoke TLS, and each answered 200 once the URL matched it.
The error
$ curl -sS https://web:8080/
curl: (35) OpenSSL/3.0.13: error:0A00010B:SSL routines::wrong version number
exit=35
Why it happens
The server on web:8080 was python3 -m http.server 8080, which
speaks plain HTTP. With https://, curl sent TLS handshake bytes instead of an
HTTP request; the server's log shows a request line of binary bytes starting
\x16\x03\x01 and its own answer, code 400, message Bad request
version. That plain HTTP reply was not what curl expected, and curl, built with
OpenSSL 3.0.13 here, printed OpenSSL's error text and exited with code 35.
In this capture there was no TLS on that port at all. The same server answered the same request without trouble once the scheme was right.
The fix
Use the scheme the port speaks. Plain HTTP on 8080:
$ curl -sS -o /dev/null -w '%{http_code}\n' http://web:8080/
200
exit=0
Or HTTPS on the port where the TLS server listens (8443 here, with its self-signed certificate passed by --cacert):
$ curl -sS --cacert /root/web.crt -o /dev/null -w '%{http_code}\n' https://web:8443/
200
exit=0
If you control the server and want HTTPS on the port you have, the server needs a TLS
listener there; in this test that was a separate six-line Python script on 8443 that wraps
http.server in ssl with a certificate made by
openssl req -x509. Passing -k did not help: the same command with
-k printed the same code 35 line, because the problem was not the certificate.
How it was reproduced
Reproduced inside ubuntu:24.04 containers on one user-defined Docker network on
Docker engine 29.9.3. The client had curl 8.5.0 (OpenSSL 3.0.13) from apt; the server
container, alias web, ran Python 3.12.3's http.server on 8080 and a
TLS wrapper of it on 8443. The containers and the network were removed afterwards.
Frequently asked
- What does curl: (35) wrong version number mean?
- In this test it meant curl tried to speak TLS to a port where a plain HTTP server listened. The reply was not TLS, and curl exited with code 35.
- How do I fix curl SSL wrong version number?
- Match the scheme to the port: use http:// for a plain HTTP port, or https:// on the port where a TLS server listens. Both returned 200 here once they matched.
- Does curl -k fix wrong version number?
- No. In this test curl -k against the plain HTTP port printed the same code 35 error, because the port spoke no TLS at all.
For the certificate error you meet once TLS is spoken, see curl: (60) SSL certificate problem: self-signed certificate. More decoded errors in the Fixes category.