,{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"What is the difference between SSL and TLS?","acceptedAnswer":{"@type":"Answer","text":"SSL is the original protocol (SSLv2, SSLv3), both deprecated. TLS is the successor (1.0, 1.1, 1.2, 1.3). Modern browsers and servers use TLS 1.2 or 1.3. The industry still uses SSL loosely to mean TLS."}},{"@type":"Question","name":"Can antivirus or security software cause SSL handshake failures?","acceptedAnswer":{"@type":"Answer","text":"Yes. SSL inspection software performs man-in-the-middle TLS termination. If the interception certificate is not trusted by the client, the handshake appears to fail. Common in corporate environments."}}]}

SSL Handshake Failed: Causes and Fixes

Quick reference

Error messagesERR_SSL_PROTOCOL_ERROR, SSL_ERROR_HANDSHAKE_FAILURE_ALERT, SSL: HANDSHAKE_FAILURE
LayerTLS (after TCP connection, before HTTP)
HTTP code?No — TLS layer failure
Cloudflare code525 SSL Handshake Failed

What SSL handshake failure means

Every HTTPS connection begins with a TLS handshake — a negotiation phase where client and server agree on a TLS version, cipher suite, and exchange certificates and session keys. If any step of this negotiation fails, the handshake is aborted and no HTTP data is exchanged. The client sees a connection error rather than an HTTP status code.

The handshake has several stages, each of which can fail independently: ClientHello (client sends supported versions and ciphers), ServerHello (server selects version and cipher), Certificate (server sends its certificate), certificate validation (client verifies the certificate), and key exchange (both sides derive the session key). A failure at any stage produces an SSL handshake failed error, with different alert codes indicating where it failed.

TLS alert codes

TLS uses alert messages to communicate handshake failures. The alert code identifies the failure type:

AlertMeaningCommon cause
handshake_failure (40)No mutually supported cipher/versionProtocol version mismatch or old cipher only
certificate_unknown (46)Certificate could not be verifiedSelf-signed, expired, wrong CA
bad_certificate (42)Certificate parsing failedMalformed certificate file
unrecognized_name (112)SNI hostname not recognizedVirtual host SNI misconfiguration
protocol_version (70)Protocol version not supportedClient or server requires newer/older TLS

Diagnosing the failure

Use openssl to identify the specific failure point:

openssl s_client -connect example.com:443 -servername example.com # Useful flags: openssl s_client -connect example.com:443 -tls1_2 # force TLS 1.2 openssl s_client -connect example.com:443 -tls1_3 # force TLS 1.3 openssl s_client -connect example.com:443 -ssl3 # test SSLv3 (should fail) # Show full cert chain: openssl s_client -connect example.com:443 -showcerts # Verbose cipher negotiation: openssl s_client -connect example.com:443 -cipher "ECDHE-RSA-AES128-GCM-SHA256"

Check what TLS versions and ciphers the server supports:

# Using nmap's ssl-enum-ciphers script: nmap --script ssl-enum-ciphers -p 443 example.com # Or sslyze (Python): pip install sslyze --break-system-packages python -m sslyze example.com

Check for SNI issues:

# With SNI (correct way): openssl s_client -connect IP:443 -servername example.com # Without SNI (wrong way — may get default/wrong certificate): openssl s_client -connect example.com:443 # Compare: do both return the same certificate?

Causes and fixes

No mutually supported TLS version. The client requires TLS 1.2+ but the server only supports TLS 1.0/1.1, or vice versa. Fix: update the server's TLS configuration to support TLS 1.2 and 1.3:

# nginx: ssl_protocols TLSv1.2 TLSv1.3; # Apache: SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1

No mutually supported cipher suite. Client and server share no cipher in common. Modern clients require ECDHE (forward secrecy) cipher suites. Old servers configured with RC4, 3DES, or NULL ciphers only will fail against modern clients:

# nginx — modern cipher configuration: 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; ssl_prefer_server_ciphers off;

Certificate issues triggering handshake abort. If the client receives a certificate it cannot validate (expired, self-signed without trust, wrong CA), it sends a certificate_unknown or bad_certificate alert and aborts. See the ERR_CERT_COMMON_NAME_INVALID guide for certificate-specific fixes.

SNI not configured. A server hosting multiple domains must use SNI to serve the correct certificate per domain. If the server does not support SNI or is not configured for it, all HTTPS requests get the same (possibly wrong) certificate. Ensure nginx has separate server blocks with ssl_certificate directives per domain, and that the server is compiled with SNI support (standard in all modern builds).

Mutual TLS (mTLS) client certificate missing. Some APIs and internal services require the client to present its own certificate. If the server expects a client certificate and the client does not send one, the handshake fails with certificate_required or handshake_failure. The client must be configured with a valid client certificate:

# curl with client certificate: curl --cert client.pem --key client.key https://api.example.com/ # Python requests: requests.get('https://api.example.com/', cert=('client.pem', 'client.key'))

Frequently asked questions

What is the difference between SSL and TLS?

SSL (Secure Sockets Layer) is the original protocol, with versions SSLv2 and SSLv3, both now deprecated and disabled. TLS (Transport Layer Security) is the successor — TLS 1.0, 1.1, 1.2, 1.3. Despite this, the industry still commonly says "SSL" when referring to TLS. All modern browsers and servers use TLS 1.2 or TLS 1.3. SSLv3 should be disabled everywhere.

Can antivirus or security software cause SSL handshake failures?

Yes. SSL inspection software (corporate proxies, antivirus tools that intercept HTTPS) performs a man-in-the-middle TLS termination. If the interception certificate is not trusted by the client, the handshake appears to fail. This is common in corporate environments where the IT-managed device trusts the inspection proxy certificate but personal devices do not.

How do I test if a specific cipher works?

Use openssl s_client with the -cipher flag: openssl s_client -connect example.com:443 -cipher "ECDHE-RSA-AES256-GCM-SHA384". A successful handshake output means the server supports that cipher. An error ("no ciphers available" or "SSL handshake failure") means it does not.

What is forward secrecy and why does it matter?

Forward secrecy means each TLS session uses a unique session key that is not derived from the server's private key. Even if the server's private key is later compromised, past recorded traffic cannot be decrypted. ECDHE key exchange provides forward secrecy. RSA key exchange (without ephemeral keys) does not. All modern TLS cipher suites use ECDHE.

Related guides

Cloudflare 525 · Cloudflare 526 · ERR_CERT_COMMON_NAME_INVALID · HTTP 101 · HTTP 426

All Guides · Home