ProductHow it worksPricing
Start free trial

On this page

  1. Find the cause in a minute
  2. The certificate has expired
  3. The certificate doesn’t cover the hostname
  4. The intermediate certificate is missing
  5. No shared TLS version or cipher
  6. The server sends the wrong certificate (SNI)
  7. Cloudflare error 525
  8. Problems on the visitor’s side
Guides

SSL handshake failed: what it means and how to fix it

7 October 2026 · 7 min read

Before any HTTPS page loads, the browser and the server agree on a TLS version and a cipher, and the server proves who it is with its certificate. That exchange is the handshake. “SSL handshake failed” means one side gave up before it finished. The name is a leftover: SSL was retired years ago, and today it’s always TLS. The error just kept the old name.

The same failure shows up under different names depending on where you see it:

  • Chrome and Edge: ERR_SSL_PROTOCOL_ERROR or ERR_SSL_VERSION_OR_CIPHER_MISMATCH
  • Firefox: SSL_ERROR_HANDSHAKE_FAILURE_ALERT or SSL_ERROR_NO_CYPHER_OVERLAP
  • curl: SSL routines::sslv3 alert handshake failure
  • Java: javax.net.ssl.SSLHandshakeException
  • Python: ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE]
  • Cloudflare: error 525, SSL handshake failed

On this page

  1. Find the cause in a minute
  2. The certificate has expired
  3. The certificate doesn’t cover the hostname
  4. The intermediate certificate is missing
  5. No shared TLS version or cipher
  6. The server sends the wrong certificate (SNI)
  7. Cloudflare error 525
  8. Problems on the visitor’s side

Find the cause in a minute

Start by working out which side is at fault. Try the site from a different device on a different network, such as a phone on mobile data.

  • Fails everywhere: the problem is on the server. Keep reading.
  • Fails on one device only: skip to problems on the visitor’s side.

For a server problem, openssl shows you exactly where the handshake stops. Replace the domain with yours:

openssl s_client -connect yourclient.com:443 -servername yourclient.com

Read the output from the top:

  • Connection refused or a timeout: nothing is listening on port 443, or a firewall is blocking it.
  • alert handshake failure straight after connecting: the two sides share no TLS version or cipher.
  • A certificate prints, followed by Verify return code: 10 (certificate has expired) or 21 (unable to verify the first certificate): the certificate itself is the problem.
  • Verify return code: 0 (ok): the server is fine for modern clients. The fault is with an older client or something in between.

curl -vI https://yourclient.com gives a shorter version of the same story. You can also run ZoneOwl’s free domain check, which shows the certificate’s expiry, issuer, hostname match and protocol in one place.

Server-side causes and fixes

1. The certificate has expired

The most common cause by far. Free certificates from Let’s Encrypt last 90 days, and renewals fail silently when a DNS record, a firewall rule or a moved server breaks the validation step. Check the dates:

echo | openssl s_client -connect yourclient.com:443 -servername yourclient.com 2>/dev/null | openssl x509 -noout -dates

Fix: renew the certificate (for Certbot, certbot renew), then reload the web server so it picks up the new file. Then find out why automatic renewal stopped, or it will happen again in 90 days.

2. The certificate doesn’t cover the hostname

A certificate for yourclient.com doesn’t automatically cover www.yourclient.com or shop.yourclient.com. Look at the subject alternative names:

echo | openssl s_client -connect yourclient.com:443 -servername yourclient.com 2>/dev/null | openssl x509 -noout -ext subjectAltName

Fix: reissue the certificate with every hostname visitors use, or redirect the missing hostname to one that is covered.

3. The intermediate certificate is missing

Servers have to send their certificate plus the intermediate certificates that link it to a trusted root. Desktop browsers often fill the gap themselves, so the site looks fine in Chrome while curl, Android apps, Java and payment webhooks fail. The giveaway is Verify return code: 21 in openssl, or PKIX path building failed in Java.

Fix: install the full chain. With Let’s Encrypt, point the server at fullchain.pem, not cert.pem. With a paid certificate, append the CA’s intermediate bundle to your certificate file.

4. No shared TLS version or cipher

Modern browsers only speak TLS 1.2 and 1.3. A server stuck on TLS 1.0 or 1.1 fails with every current browser. The reverse happens too: a server hardened to TLS 1.3 only will reject older clients, such as legacy payment terminals, old Android versions or an outdated Java runtime calling your API. Test each version:

openssl s_client -connect yourclient.com:443 -servername yourclient.com -tls1_2
openssl s_client -connect yourclient.com:443 -servername yourclient.com -tls1_3

Fix: enable TLS 1.2 and 1.3 and use a current cipher list. Mozilla’s SSL Configuration Generator gives a tested config for Nginx, Apache, HAProxy and others.

5. The server sends the wrong certificate (SNI)

When one server hosts many sites, the client says which hostname it wants during the handshake (this is called SNI), and the server picks the matching certificate. If the site isn’t configured for that name, the server falls back to a default certificate or aborts. Compare the output with and without -servername. If they differ and the one with it is wrong, the virtual host is misconfigured.

Fix: check that the server block or virtual host for this hostname exists, listens on 443 with SSL enabled, and points at the right certificate.

6. Cloudflare error 525

Error 525 is a handshake failure between Cloudflare and your origin server, not between the visitor and Cloudflare. It usually appears when the SSL/TLS mode is Full or Full (strict) and the origin has no working certificate on port 443. Run the openssl test against the origin’s IP address directly:

openssl s_client -connect ORIGIN_IP:443 -servername yourclient.com

Fix: install a valid certificate on the origin. A free Cloudflare Origin CA certificate works for Full (strict). Then make sure port 443 is open to Cloudflare’s IP ranges. Switching the mode to Flexible makes the error go away but sends traffic to your origin unencrypted, so avoid it.

Problems on the visitor’s side

When the site works everywhere except one device, check these in order:

  1. The device clock. If the date is wrong, every certificate looks expired or not yet valid. Turn on automatic date and time.
  2. Antivirus or a corporate proxy. HTTPS scanning in antivirus software, and company firewalls that inspect traffic, intercept the handshake with their own certificate. Try with the feature turned off or on another network.
  3. An out-of-date browser or operating system. Very old systems don’t trust newer root certificates or support TLS 1.2. Update, or try another browser.
  4. Cached state. Clear the browser’s cache and, on Windows, the SSL state in Internet Options. Restart the browser.

Stop it happening on client sites

Most handshake failures on agency-managed sites are certificates that expired after a silent renewal failure, or a server change that dropped the intermediate chain. Both are visible days or weeks ahead if something is watching. ZoneOwl checks the certificate on every client domain daily and alerts you before it expires or when the chain, hostname or issuer changes.

Questions

Is "SSL handshake failed" a problem with my computer or the website?
If one site fails on every device and network, it is the website. If many sites fail on one device, look at that device: its clock, antivirus HTTPS scanning, a corporate proxy, or an outdated browser or operating system.
What is Cloudflare error 525?
Error 525 means Cloudflare reached your origin server but couldn’t complete a TLS handshake with it. Visitors’ connections to Cloudflare are fine. The usual causes are no certificate on the origin, port 443 closed or not listening for TLS, or SNI and cipher settings that don’t match what Cloudflare sends.
Can an expired certificate cause a handshake failure?
Yes. Browsers show it as a certificate error such as NET::ERR_CERT_DATE_INVALID, but many other clients, including Java, Python, curl and API integrations, report it as a failed handshake because certificate checks happen during the handshake.
Does disabling certificate verification fix it?
It hides it. Flags like curl -k or verify=False stop the client checking who it is talking to, which removes the protection TLS exists for. Use them only to confirm a diagnosis, never as the fix.

Catch certificate problems before clients do

ZoneOwl watches SSL certificates, domain renewals, DNS and lookalike domains for every client and tells you before something breaks.

Start 14-day free trial Check a domain free

Watch every client domain

SSL, renewals, DNS and lookalikes, checked daily.

Start free trial

Early warnings for every client domain your agency looks after.

Product

  • Overview
  • How it works
  • Pricing
  • DNS monitoring
  • Log in

Free tools

  • Domain check
  • Expiry checker
  • Nameserver lookup

Resources

  • Guides
  • Privacy
  • Terms
© 2026 ZoneOwlSSL · Renewal · Email DNS · Lookalikes