Short answer: ERR_SSL_VERSION_OR_CIPHER_MISMATCH means the browser and the server found no TLS version or cipher suite they both accept, so the handshake stopped at its first step. Usually the server offers only TLS 1.0 or 1.1, a cipher list of retired suites, or no certificate for that name. Visitors can rarely fix it; the site owner enables TLS 1.2 and 1.3.
Chrome and Edge show it under the heading “This site can’t provide a secure connection” with the line “example.com uses an unsupported protocol.” Chromium’s source describes the code, number -113, as: “The client and server don’t support a common SSL protocol version or cipher suite.” Firefox reports the same situations as SSL_ERROR_UNSUPPORTED_VERSION or SSL_ERROR_NO_CYPHER_OVERLAP. The same heading with ERR_SSL_PROTOCOL_ERROR under it is a different failure, usually plain HTTP on the HTTPS port.
What the error means
A TLS connection opens with the browser’s ClientHello: the TLS versions it speaks, the cipher suites it accepts and the hostname it wants (SNI). The server picks one version and one suite from those lists and sends its certificate for that name. If it cannot pick, it answers with an alert and the connection ends.
Chromium’s error mapping (net/ssl/openssl_ssl_util.cc) shows when Chrome chooses this code: the server sent a protocol_version alert, the versions did not overlap, no cipher suite was shared, or the server answered the ClientHello itself with a handshake_failure alert. That last case is not always about versions: servers and CDNs that have no certificate for the requested name often refuse the handshake the same way, and Chrome cannot tell the difference.
Current browsers speak TLS 1.2 and TLS 1.3 only. TLS 1.0 and 1.1 were formally deprecated by RFC 8996 in March 2021, and RC4 has been prohibited in TLS since RFC 7465 in 2015. A server that offers nothing newer, or only suites like those, has nothing left to agree on.
Causes at a glance
| Cause | Who sees it | Confirm with | Section |
|---|---|---|---|
| The server offers only TLS 1.0 or 1.1 | Everyone with a current browser | -tls1_2 and -tls1_3 both fail | Cause 1 |
| No cipher suite in common | Everyone, or every TLS 1.2 client | Server log: no shared cipher | Cause 2 |
| A CDN has no certificate for that name | Everyone on that one hostname | The apex works, a deeper subdomain fails | Cause 3 |
| The name reaches another, older server or device | Everyone on that name, or only IPv6 users | Test each A and AAAA address | Cause 4 |
| A firewall, proxy or antivirus in between | One network or one device | The site works over mobile data | Cause 5 |
If you are a visitor
- Try another network and another device. If the site works over your phone’s mobile data, something on your network or computer is in the way: a company proxy, a VPN, or antivirus that scans HTTPS. Turn the scanning off for a test.
- Update the browser and the system. A browser from years ago may lack TLS 1.3 or the suites a strict server requires.
- Skip the usual tips. Clearing cookies, the cache or the Windows SSL state changes nothing here, and the TLS checkboxes in Windows’ Internet Options only affect programs that use Windows’ own TLS; Chrome, Edge and Firefox bring their own. Do not try to switch old TLS versions back on in a browser.
- If everything else works, the site is broken for everyone. Tell its owner; there is nothing safe you can change on your side.
Site owner: test each TLS version from outside
# TLS 1.2 and TLS 1.3, one at a time
openssl s_client -connect example.com:443 -servername example.com -tls1_2 -brief </dev/null
openssl s_client -connect example.com:443 -servername example.com -tls1_3 -brief </dev/null
# curl: --tlsv1.2 means "1.2 or newer"; add --tls-max 1.2 for exactly 1.2
curl -sv -o /dev/null --tlsv1.2 https://example.com/ 2>&1 | grep -E '^\* (TLS|SSL)|^curl'
curl -sv -o /dev/null --tlsv1.2 --tls-max 1.2 https://example.com/ 2>&1 | grep -E '^\* (TLS|SSL)|^curl'
# Every version and cipher suite the server accepts (package: nmap)
nmap --script ssl-enum-ciphers -p 443 example.comA working version prints CONNECTION ESTABLISHED followed by Protocol version: TLSv1.3 (or TLSv1.2) and the suite. We reproduced each failure against test servers on 127.0.0.1 on Debian 12 with OpenSSL 3.0.22 and curl 7.88.1. These are the lines they printed:
| Server side | Client test | Output |
|---|---|---|
| Only TLS 1.1 | s_client -tls1_2 | ssl_choose_client_version:unsupported protocol |
| Only TLS 1.1 | curl --tlsv1.2 | curl: (35) OpenSSL/3.0.22: error:0A00042E:SSL routines::tlsv1 alert protocol version |
| Only TLS 1.1 | plain s_client or curl | legacy sigalg disallowed or unsupported |
| Only TLS 1.3 | s_client -tls1_2 | tlsv1 alert protocol version ... SSL alert number 70 |
| TLS 1.2, no common suite | s_client | sslv3 alert handshake failure ... SSL alert number 40 |
| TLS 1.2, no common suite | the server's own log | tls_post_process_client_hello:no shared cipher |
The third row is OpenSSL 3 refusing the old signature scheme of TLS 1.0 and 1.1 at its default security level, which is the client-side face of the same problem. To see what such a server does speak, lower the level for this one test; against our TLS 1.1-only server it connected:
openssl s_client -connect example.com:443 -servername example.com \
-tls1_1 -cipher 'DEFAULT:@SECLEVEL=0' -brief </dev/nullCONNECTION ESTABLISHED
Protocol version: TLSv1.1
Ciphersuite: ECDHE-ECDSA-AES256-SHAnmap gives the whole picture at once. Against the same server it listed one version and two suites, nothing a current browser accepts:
PORT STATE SERVICE
43762/tcp open unknown
| ssl-enum-ciphers:
| TLSv1.1:
| ciphers:
| TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (secp256r1) - A
| TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (secp256r1) - A
| compressors:
| NULL
| cipher preference: client
|_ least strength: AThe letter grades rate each suite on its own; what matters is that no TLSv1.2 or TLSv1.3 section exists. Run nmap only against servers you are responsible for. The openssl commands guide shows which versions and suites your local OpenSSL build supports.
Our SSL checker runs a handshake from Amsterdam and reports the protocol and certificate it got, without a terminal.
Cause 1: the server only speaks TLS 1.0 or 1.1
Typical sources are old appliances and load balancers, Windows Server 2008 R2 and older (Microsoft’s Schannel table lists TLS 1.2 there as disabled by default, or not supported at all), Java applications on very old runtimes, and protocol lines copied from old hardening guides. Enable TLS 1.2 and 1.3.
nginx
ssl_protocols TLSv1.2 TLSv1.3;Replace the existing ssl_protocols line rather than adding a second one, and set it in the http block: nginx before 1.29.2 negotiates the version before it knows which server block the client wants, so the line inside a non-default server block has no effect. The complete Mozilla-based configuration, with ciphers and a default server, is in our SSL handshake guide. Then sudo nginx -t && sudo systemctl reload nginx.
Apache
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder offPer the mod_ssl documentation, Apache honours SSLProtocol per name-based virtual host only from 2.4.42 on, built against OpenSSL 1.1.1 or later; older builds use the setting of the first virtual host on that IP:port. A global setting applies to every virtual host that has none of its own. Check with sudo apachectl configtest and reload with sudo systemctl reload apache2.
IIS and other Windows services
Windows decides the versions system-wide through Schannel. Per Microsoft’s table, TLS 1.2 is on by default from Windows Server 2012, and TLS 1.3 is supported from Windows Server 2022 (not on 2019). On a current server this error therefore means something switched TLS 1.2 off: a hardening script, a registry import or a cipher suite policy. Look for overrides:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols" /sA TLS 1.2\Server key with Enabled set to 0 is the culprit: set it to 1 or delete the override, then restart the server, since services keep their TLS settings until they restart. In PowerShell, Get-TlsCipherSuite lists the suites that are still enabled; if that list is nearly empty, a cipher policy removed them.
Cause 2: no cipher suite in common
The versions overlap, but the server’s cipher list leaves nothing the browser offers. That happens with lists from old hardening guides (RC4, 3DES, export suites, or only finite-field DHE suites that Chrome dropped years ago) and, more and more often, with a mismatch between list and key type.
Certbot has created ECDSA keys by default since version 2.0. A cipher list copied from a guide that names only ECDHE-RSA-… suites then has no suite for that certificate in TLS 1.2. TLS 1.3 negotiates its suites separately, so browsers keep working until someone removes TLSv1.3 from the protocols. We ran exactly this pair, an ECDSA certificate with an RSA-only list, against a test server on Debian 12 with OpenSSL 3.0.22:
# s_client -brief, TLS 1.3 allowed
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
# s_client -tls1_2 -brief
4037AF452C7F0000:error:0A000410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1602:SSL alert number 40
# the test server's own log for that attempt
40A738028B7F0000:error:0A0000C1:SSL routines:tls_post_process_client_hello:no shared cipher:../ssl/statem/statem_srvr.c:2226:Use Mozilla’s “intermediate” list, which covers both key types. As of October 2026, version 6.0 of its guidelines (published as JSON at ssl-config.mozilla.org/guidelines/latest.json) allows TLS 1.2 and 1.3 with the six ECDHE suites in the Apache block above; the generator at ssl-config.mozilla.org writes them for nginx, Apache, HAProxy and others. nginx logs no shared cipher only at the info level, so a stock error log stays silent; the handshake guide shows how to raise it for a few minutes.
Cause 3: a CDN has no certificate for that name
Behind a CDN, the handshake happens at the CDN’s edge, with the edge’s certificate. If that certificate does not cover the hostname, the edge refuses the handshake and Chrome shows this code, although nothing is wrong with versions or ciphers. Cloudflare’s troubleshooting page for this error (read 21 October 2026) names four causes: a certificate that is not active yet, a record that is not proxied, an expired custom certificate, and a multi-level subdomain. Its Universal SSL certificate covers the apex and one level of subdomain:
| Hostname | Covered |
|---|---|
example.com | Yes |
www.example.com | Yes |
docs.example.com | Yes |
dev.docs.example.com | No: two levels below the apex |
For a deeper name, rename the host to one level (dev-docs.example.com) or add a certificate that covers it; Cloudflare’s page names Total TLS, an advanced certificate or an uploaded custom certificate for that. A hostname or zone added minutes ago may only need to wait until its edge certificate is active.
Cause 4: the name reaches another server
The server you fixed is fine, but some visitors reach a different one: an old A or AAAA record that points at a retired machine, a port forward on 443 to an old device, or a load balancer listener with an outdated TLS policy. Test every address on its own:
dig +short example.com A
dig +short example.com AAAA
openssl s_client -connect 203.0.113.10:443 -servername example.com -tls1_2 -brief </dev/null
openssl s_client -connect '[2001:db8::10]:443' -servername example.com -tls1_2 -brief </dev/nullAn nginx server that refuses names it does not host with ssl_reject_handshake on; sends a different alert, unrecognized_name, and Chrome then shows ERR_SSL_UNRECOGNIZED_NAME_ALERT instead. Seeing that code means the name does reach your server, but no server block lists it in server_name.
Cause 5: something between browser and server
Firewalls, proxies and antivirus products that inspect HTTPS make their own TLS connection to the site and a second one to your browser. An outdated one may support only old versions or suites on one side, and the error then appears only on that network or that computer. Update its firmware or rules, or exempt the site from inspection. If the error comes and goes with a VPN, the VPN provider’s filtering is the middlebox.
After the fix
-tls1_2and-tls1_3both printCONNECTION ESTABLISHED, for every name and every address, IPv6 included.nmap --script ssl-enum-ciphersshows aTLSv1.2and aTLSv1.3section and nothing older.- A TLS 1.2-only client still connects (
--tls-max 1.2), so older apps and payment callbacks are not locked out by a TLS 1.3-only setting.
The stock nginx on Debian 12 already offers TLS 1.2 and 1.3, so on a fresh Linux VPS this error almost always comes from an edited protocol or cipher line, and you fix it as root in a minute. On a Windows VPS with Windows Server 2022, IIS speaks TLS 1.3 out of the box; with 2019 it tops out at TLS 1.2, which every current browser accepts.
Frequently asked
What does ERR_SSL_VERSION_OR_CIPHER_MISMATCH mean?
Chrome and the server found no TLS version or cipher suite they both accept, so the handshake stopped at its first step. Usually the server offers only TLS 1.0 or 1.1, its cipher list contains no suite the browser supports, or a CDN has no certificate for that hostname.
How do I fix ERR_SSL_VERSION_OR_CIPHER_MISMATCH on my server?
Enable TLS 1.2 and 1.3 and use a current cipher list such as Mozilla's intermediate configuration: ssl_protocols TLSv1.2 TLSv1.3 in the http block of nginx, SSLProtocol -all +TLSv1.2 +TLSv1.3 in Apache. Then test from outside with openssl s_client -brief, once with -tls1_2 and once with -tls1_3; both should print CONNECTION ESTABLISHED.
Can I fix ERR_SSL_VERSION_OR_CIPHER_MISMATCH as a visitor?
Only if something on your side is in the way: try another network, turn off antivirus HTTPS scanning or the VPN for a test, and update the browser. Clearing the cache or the SSL state does not help. If the site fails on every network and device, only its owner can fix it.
Why does only one subdomain show ERR_SSL_VERSION_OR_CIPHER_MISMATCH behind Cloudflare?
Cloudflare's Universal SSL certificate covers the apex domain and one level of subdomain, so a name such as dev.docs.example.com has no edge certificate and the handshake is refused. Use a one-level name, or add a certificate that covers the deeper name.