Skip to content
RU

SSL routines: wrong version number. The Other End Is Not Speaking TLS

What it means: The client started TLS, but the server answered with something that is not TLS, usually plain HTTP.

  1. Check the port and URL scheme
  2. Check https_proxy uses http://
  3. Server: add ssl to the listen line
  4. Mail: 465 is TLS, 587 is STARTTLS

Test your URL now

Runs a full TLS check: handshake, protocol versions, certificate chain, trust and expiry.

Check your site's SSL →

What wrong version number means

OpenSSL reason 267, SSL_R_WRONG_VERSION_NUMBER, string wrong version number. Every TLS record starts with a type byte and a protocol version; when the first bytes the client receives do not look like a TLS record header, OpenSSL stops with this reason. The answer it got was not a TLS ServerHello at all. The most common thing on the other end is a plain HTTP server, whose HTTP/1.1 400 or HTTP/1.1 200 starts with bytes that OpenSSL tries to read as a version.

The packed error code tells you the OpenSSL generation. OpenSSL 3 prints error:0A00010B:SSL routines::wrong version number (library 20 shifted into the top bits, reason 0x10B); OpenSSL 1.1.1 printed error:1408F10B:SSL routines:ssl3_get_record:wrong version number (sslerr.h, ssl_err.c). You meet it as:

  • curl: exit 35, curl: (35) ... wrong version number
  • Python: ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number
  • Node.js: code: 'ERR_SSL_WRONG_VERSION_NUMBER'

Despite the name, it is almost never about TLS 1.2 versus 1.3. A real version disagreement produces tlsv1 alert protocol version or a handshake failure instead.

Causes

CauseExampleFix
https:// to a plain-HTTP porthttps://example.com:8080/ where the app listens without TLSUse http:// for that port, or terminate TLS in front of it
Proxy URL with the wrong schemehttps_proxy=https://proxy:3128 for an ordinary HTTP proxyWrite https_proxy=http://proxy:3128
Server listens on 443 without TLSnginx listen 443; with no ssl parameterlisten 443 ssl;
Wrong mail port modeImplicit TLS on 587, or STARTTLS on 465465 = TLS from the first byte, 587 = STARTTLS
Something in the path answers in clear textCaptive portal, transparent proxy, load balancer health pageTest from another network; fix the device

The proxy case catches many people because the variable is called https_proxy. It names the proxy used for HTTPS requests, and the scheme in its value describes how to talk to the proxy. curl treats an https:// proxy as an HTTPS proxy and starts TLS to it (curl manual, --proxy); a Squid listening in plain HTTP on 3128 answers with HTTP, and you get wrong version number before the request even leaves for the real site.

The mail case follows RFC 8314: port 465 carries mail submission over implicit TLS, while 587 starts in clear text and upgrades with STARTTLS (RFC 8314). Python's smtplib.SMTP_SSL on 587 fails with exactly this error.

Prove what the port speaks

curl -v http://example.com:443/
# < HTTP/1.1 200 OK   -> the "TLS" port is answering in plain HTTP
openssl s_client -connect example.com:443 -servername example.com </dev/null
# ... SSL routines::wrong version number

If plain HTTP to the TLS port works, the server is misconfigured. If the server is fine from your laptop but not from a CI runner or office machine, look at the environment of the failing one:

env | grep -i _proxy
curl -v --noproxy '*' https://example.com/

Success with --noproxy '*' means the proxy setting is the cause. For mail servers, test both modes explicitly:

openssl s_client -connect mail.example.com:465 -brief </dev/null
openssl s_client -connect mail.example.com:587 -starttls smtp -brief </dev/null

How to fix it

  1. Client URL: use https:// only on ports where TLS is configured. An app server on 8080 or 3000 usually expects http:// unless you set up TLS on it.
  2. Proxy variables: set http_proxy and https_proxy to http://proxy.example.com:3128 unless your proxy really accepts TLS on that port. Check /etc/environment, CI variables, Docker daemon proxy settings and ~/.npmrc as well as the shell.
  3. nginx: every TLS port needs the ssl parameter: listen 443 ssl; (and listen [::]:443 ssl;). Run nginx -T | grep -n 'listen' to find a 443 listener without it, often a second server block that wins for some names.
  4. Load balancers: if TLS is terminated at the balancer, the backend speaks HTTP. A client that bypasses the balancer and calls the backend with https:// gets this error.
  5. SMTP clients: pair 465 with implicit TLS (SMTP_SSL, secure: true) and 587 with STARTTLS (starttls(), secure: false).

How to confirm the fix

openssl s_client -connect example.com:443 -servername example.com -brief </dev/null
# Protocol version: TLSv1.3
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com/
# 200

The SSL/TLS checker connects to port 443 of your host and reports the negotiated protocol and certificate, so a plain-HTTP listener on 443 shows up immediately.

Related errors

CertificateExpiry, issuer, domains (SAN)
ChainIntermediate and root CA validation
TLS ProtocolTLS version and cipher suite
VulnerabilitiesHeartbleed, POODLE, weak ciphers

Why teams trust us

TLS 1.3
supported
Full
CA chain check
3,158
checks in 30 days
30/14/7
days-to-expiry alerts

How it works

1

Enter domain

2

TLS chain verified

3

Expiry date & vulnerabilities

What Does the SSL Check Cover?

SSL/TLS is the encryption protocol that protects data between the browser and server. Our tool analyzes the certificate, chain of trust, TLS version, and knownvulnerabilities.

Certificate Details

Issuer, validity period, signature algorithm, covered domains (SAN), and validation type (DV/OV/EV).

Chain of Trust

Full chain verification: from leaf certificate through intermediates to root CA.

TLS Analysis

Protocol version (TLS 1.2/1.3), cipher suites, Perfect Forward Secrecy (PFS) support.

Expiry Alerts

Set up a monitor — get Telegram and email alerts 30/14/7 days before expiration.

DV vs OV vs EV Certificates

DV (Domain Validation)
  • Confirms domain ownership only
  • Issued in minutes automatically
  • Free via Let's Encrypt
  • Suitable for most websites
  • Most common certificate type
OV / EV
  • Organization (OV) or Extended Validation (EV)
  • Issued in 1-5 business days
  • Costs $50 to $500/year
  • For finance, e-commerce, government sites
  • Increases user trust

Who uses this

DevOps

SSL certificate monitoring

Security

TLS config audit

SEO

HTTPS as ranking factor

E-commerce

customer trust

Common Mistakes

Expired certificateBrowsers block sites with expired SSL. Set up auto-renewal or monitoring.
Incomplete certificate chainWithout intermediate CA, some browsers and bots cannot verify the certificate.
Mixed content on HTTPS siteHTTP resources on an HTTPS page — the browser lock icon disappears, reducing trust.
Using TLS 1.0/1.1Legacy TLS versions have known vulnerabilities. Use TLS 1.2+ or 1.3.
Domain mismatch in certificateThe certificate must cover all site domains, including www and subdomains.

Best Practices

Set up auto-renewalLet's Encrypt + certbot with cron — certificate renews automatically every 60-90 days.
Enable HSTSStrict-Transport-Security header forces browsers to always use HTTPS.
Use TLS 1.3TLS 1.3 is faster (1-RTT handshake) and safer — legacy ciphers removed.
Monitor expiration datesCreate a monitor on Enterno.io — get notified well before expiration.
Verify chain after renewalAfter certificate renewal, confirm that intermediate certificates are installed.

Get more with a free account

SSL certificate monitoring, check history and alerts 30 days before expiry.

Sign up free

Learn more

Sources

Frequently Asked Questions

Does wrong version number mean I need to change the TLS version?

Almost never. It means the reply was not TLS at all, typically plain HTTP on the port you treated as HTTPS. A real version mismatch gives a protocol version alert instead.

Why do I get wrong version number only behind the corporate proxy?

Your https_proxy variable probably starts with https:// although the proxy speaks plain HTTP. Change it to http://proxy-host:port.

What does error:0A00010B mean?

It is OpenSSL 3's packed code for the SSL library and reason 267, wrong version number. In OpenSSL 1.1.1 the same reason appeared as 1408F10B.

Which SMTP port uses SSL and which uses STARTTLS?

Port 465 uses implicit TLS from the first byte; port 587 starts in plain text and upgrades with STARTTLS. Mixing them up gives wrong version number.

Can a server cause this error?

Yes. An nginx listen 443 line without the ssl parameter serves plain HTTP on the HTTPS port, and every TLS client fails with wrong version number.

Try the live tool that powered this guide

Free plan — 10 monitors, checks every 5 min, no card required. Upgrade for 1-minute interval and multi-region monitoring.