TL;DR
Your server speaks TLS 1.0 or TLS 1.1. Modern browsers stopped accepting both in early 2020 โ Chrome 84 and Firefox 74 both dropped them. Enable TLS 1.2/1.3, disable the old versions, and you're done.
# Nginx โ drop this into your server block or http block
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
Reload Nginx after the change: sudo systemctl reload nginx
What This Error Means
ERR_SSL_VERSION_OR_CIPHER_MISMATCH shows up when the TLS handshake fails before a single byte of your page is transferred. Three things can cause it:
- The server only offers TLS 1.0 or TLS 1.1. Chrome 84 (August 2020) and Firefox 74 (March 2020) both removed support for these.
- Every cipher suite on the server is considered insecure and has been stripped from modern clients.
- The SSL certificate's Common Name doesn't match the domain โ less common, but it throws the same error code.
Nine times out of ten it's a server that was configured in 2014 and never touched since. Old config, new browser, handshake fails.
Check Your Current TLS Configuration
Before editing anything, find out what your server is actually advertising:
# From any Linux machine with openssl installed
openssl s_client -connect yourdomain.com:443 -tls1
openssl s_client -connect yourdomain.com:443 -tls1_1
openssl s_client -connect yourdomain.com:443 -tls1_2
openssl s_client -connect yourdomain.com:443 -tls1_3
If -tls1 or -tls1_1 connects cleanly but -tls1_2 fails โ that's your problem right there. For a cipher-level breakdown, nmap is faster:
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
Want a full graded report? Run SSL Labs Server Test (search "ssllabs server test"). It lists every supported protocol and flags deprecated ones with a big red F.
Fix on Nginx
Open your Nginx config โ usually /etc/nginx/nginx.conf or a site file under /etc/nginx/sites-available/. Find the SSL block and replace it:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Replace any existing ssl_protocols line with this:
ssl_protocols TLSv1.2 TLSv1.3;
# Modern cipher list โ drop weak ciphers
ssl_ciphers 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:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
}
# Test config, then reload
nginx -t
sudo systemctl reload nginx
Fix on Apache
Edit your virtual host config or /etc/apache2/mods-enabled/ssl.conf. The key directive is SSLProtocol โ the minus signs explicitly disable old versions:
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# Disable old protocols
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# Modern cipher suites only
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
</VirtualHost>
# Verify and restart
apache2ctl configtest
sudo systemctl restart apache2
Fix on Node.js (HTTPS server)
Running a custom Node.js HTTPS server? Pass TLS options explicitly in the createServer call:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
minVersion: 'TLSv1.2', // reject anything below TLS 1.2
ciphers: [
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-CHACHA20-POLY1305',
].join(':'),
};
https.createServer(options, app).listen(443);
When You're the Client, Not the Server
Calling a third-party API and hitting this error? The remote server is broken โ yours is fine. Your options:
- Contact the API provider. Ask them to enable TLS 1.2. That's the real fix.
- If you need a short-term workaround for internal systems while waiting, you can constrain your HTTP client to TLS 1.2 explicitly:
# Python requests โ force TLS 1.2 minimum via custom adapter
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
class TLS12Adapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
ctx = create_urllib3_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
kwargs['ssl_context'] = ctx
super().init_poolmanager(*args, **kwargs)
session = requests.Session()
session.mount('https://', TLS12Adapter())
response = session.get('https://old-api.example.com/endpoint')
Do not downgrade your client to accept TLS 1.0/1.1 in production. That defeats the entire purpose.
OpenSSL Version Check
TLS 1.3 requires OpenSSL 1.1.1 or later. Anything older and TLS 1.3 simply isn't available, regardless of what you put in nginx.conf.
openssl version
# Need at least OpenSSL 1.1.1 for TLS 1.3 support
Stuck on OpenSSL 1.0.x? Upgrade the library first, then update your server config:
# On Debian/Ubuntu
sudo apt update && sudo apt install openssl libssl-dev
# On CentOS/RHEL 8+
sudo dnf install openssl
Verify the Fix
# Confirm TLS 1.2 works
openssl s_client -connect yourdomain.com:443 -tls1_2
# Should show: SSL handshake has read ... bytes
# Look for: Protocol: TLSv1.2
# Confirm old TLS is rejected
openssl s_client -connect yourdomain.com:443 -tls1_1
# Should fail with: alert handshake failure or similar
# Confirm TLS 1.3 works (if supported)
openssl s_client -connect yourdomain.com:443 -tls1_3
Open your site in Chrome. The error should be gone and the padlock should appear. Click it โ Connection is secure โ Certificate is valid to confirm which protocol version is active.
Certificate CN Mismatch (Same Error, Different Cause)
A hostname mismatch triggers ERR_SSL_VERSION_OR_CIPHER_MISMATCH in some browsers โ confusingly, it's the same error code. Check with:
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -subject -subj_hash
# subject= CN=yourdomain.com
# Or check SANs
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
The CN or at least one SAN entry must match the domain you're connecting to. If neither does, reissue the certificate for the correct domain.

