Error message
curl: (35) TLS connect error: error:0A00010B:SSL routines::wrong version number
Also printed as
- curl: (35) error:0A00010B:SSL routines::wrong version number
- curl: (35) error:1408F10B:SSL routines:ssl3_get_record:wrong version number
Recent curl releases (8.14.1 here) put "TLS connect error: " before the OpenSSL reason; curl 7.x printed the reason alone. OpenSSL 1.1.1 builds print the long form "error:1408F10B:SSL routines:ssl3_get_record:wrong version number"; OpenSSL 3.x prints "error:0A00010B:SSL routines::wrong version number".
curl (OpenSSL backend) — CURLE_SSL_CONNECT_ERROR, SSL_R_WRONG_VERSION_NUMBER
What it means
curl sent a TLS ClientHello and the first bytes that came back were not a TLS record. OpenSSL reads the record header's version field from that reply and finds garbage, typically the letters of "HTTP/1.1 400" from a plain-HTTP server. Despite the wording, this is almost never about TLS versions: the other side is not speaking TLS on that port.
Why it happens
https:// on a port that serves plain HTTP
commonDevelopment servers on 8080 or 3000, a backend behind a load balancer, or a misconfigured listen directive answer with HTTP. Swapping http and https in the URL, or using the TLS port number with http://, is the most common origin of this message.
The proxy URL says https:// but the proxy speaks HTTP
commonHTTPS_PROXY=https://proxy:3128 makes curl start TLS with the proxy itself. Most forward proxies expect plain HTTP from the client and open an encrypted CONNECT tunnel to the destination, so the proxy URL should start with http:// even for HTTPS traffic.
Implicit TLS against a STARTTLS port
occasionalSMTP on 25/587, IMAP on 143, POP3 on 110, LDAP on 389 and PostgreSQL/MySQL greet in plain text and upgrade later. Starting with a TLS handshake there fails immediately.
A captive portal or filter answers instead of the server
occasionalHotel and airport Wi-Fi, parental filters and some firewalls intercept port 443 and reply with an HTTP redirect page before any TLS takes place.
How to fix it
- 1.
Check what the port actually speaks
Request the same port with http://. If you get an HTTP response, either use http:// or the real TLS port; openssl s_client confirms which ports complete a TLS handshake.
bash # What does the port speak? An HTTP status line means plain HTTP. curl -sS -i http://api.example.com:8080/ | head -1 # HTTP/1.1 200 OK -> not TLS openssl s_client -connect api.example.com:8443 -brief </dev/null # handshake summary -> TLS - 2.
Use http:// for the proxy URL
Unless your proxy explicitly supports TLS to the proxy, write the proxy as http://host:port. The connection to the destination is still end-to-end TLS through the CONNECT tunnel.
bash # Most corporate proxies accept plain HTTP from the client and tunnel HTTPS with CONNECT export HTTPS_PROXY=http://proxy.example.net:3128 # http:// even for HTTPS traffic curl -x http://proxy.example.net:3128 https://api.example.com/ - 3.
Use STARTTLS on STARTTLS ports
For mail protocols, curl upgrades with --ssl-reqd on the submission and IMAP ports, or uses implicit TLS on 465 and 993 with the smtps:// and imaps:// schemes.
bash # Port 587/25 (SMTP) and 143 (IMAP) start in plain text and upgrade with STARTTLS curl --ssl-reqd smtp://mail.example.com:587 -v # Implicit TLS lives on 465 (SMTPS) and 993 (IMAPS) curl smtps://mail.example.com:465 -v - 4.
Server owners: enable TLS on the listener
If clients should use https:// on this port, the listener needs TLS turned on and a certificate configured; otherwise publish the correct port.
text # nginx: the port that clients reach with https:// needs the ssl flag server { listen 443 ssl; ssl_certificate /etc/nginx/tls/fullchain.pem; ssl_certificate_key /etc/nginx/tls/privkey.pem; }
Related errors
SSL routines:tls_validate_record_header:wrong version numberOpenSSL 3 (openssl s_client and any OpenSSL-based client)code: 'ERR_SSL_WRONG_VERSION_NUMBER'Node.js tls.connect / fetch (undici)[SSL: WRONG_VERSION_NUMBER] wrong version numberPython ssl module (OpenSSL)http: server gave HTTP response to HTTPS clientGo net/httpjavax.net.ssl.SSLException: Unsupported or unrecognized SSL messageJava (JSSE)