Article

How to Fix SSL Handshake Failed

An SSL handshake failure means the browser and server couldn't complete the TLS negotiation — caused by a protocol or cipher mismatch, an incomplete or invalid certificate, SNI issues, or a clock error. Reproduce it with openssl s_client to see exactly where the handshake breaks.

By Paul Rudenko, Security ResearcherUpdated Jun 26, 20267 min read

An SSL handshake failure means the browser and server couldn't complete the TLS negotiation — caused by a protocol or cipher mismatch, an incomplete or invalid certificate, SNI issues, or a clock error. Reproduce it with openssl s_client to see exactly where the handshake breaks.

What does "SSL handshake failed" mean?

Before any encrypted data flows over HTTPS, the client and server run a short negotiation called the TLS handshake: a defined sequence in which the two sides agree on a protocol version, choose a cipher suite, exchange and validate the server's certificate, and derive the shared keys that will encrypt the session.

If any step in that sequence cannot complete, the connection is aborted and you see a "handshake failed" error rather than the page. The exact message sequence is defined in RFC 8446 §2, the TLS 1.3 handshake protocol.

The handshake is deliberately strict. It fails closed — if the two sides cannot find a protocol they both support, if the certificate does not validate, or if the server cannot identify which site is being requested, neither party will fall back to an insecure connection. That strictness is what makes the error feel abrupt, but it is also why a single misconfiguration anywhere in the chain produces the same generic message.

The practical consequence is that "handshake failed" is a category, not a single cause. The fastest path to a fix is to identify which handshake step broke. The rest of this guide is about doing exactly that.

If you're just visiting

Handshake failures are overwhelmingly server-side, so there is usually little a visitor can change. Still, a few local conditions can break the negotiation, and they are quick to rule out:

  • Check your clock. TLS validates the certificate against the current time. If your device's date or time is wrong — common after a dead battery or a fresh OS install — every certificate looks expired or not-yet-valid and the handshake fails. Enable automatic, network-synced time.
  • Update your browser and operating system. Very old clients may not support the modern protocol versions or cipher suites the server now requires, so they cannot agree on a common set during negotiation.
  • Test a different network. Corporate proxies, security appliances, captive Wi-Fi portals, and some antivirus "HTTPS scanning" features intercept TLS and can break the handshake. Try mobile data or another network to isolate this.

If the site fails for you on multiple networks and devices but works for others, the problem is likely local. If it fails for everyone, it is the server's — keep reading the owner section, or report it to the site.

If you own the site

Don't guess. The handshake reports precisely where it stops, so the first move is always to reproduce it from the command line and read the output. From a machine that can reach your server, run:

openssl s_client -connect host:443 -servername host

Replace host with your domain. The -servername flag sends the SNI hostname, which mirrors what a real browser does — omitting it is a common reason a command-line test "works" while browsers fail. Read the output top to bottom: the protocol and cipher actually negotiated, the certificate chain the server presented, the verify return code, and any error at the point the handshake stopped.

Protocol or cipher mismatch

If the output shows no protocols available or a handshake failure alert, the two sides share no common protocol version or cipher suite. This happens when a server is locked to TLS 1.2+ while an old client only offers TLS 1.0/1.1, or when a hardened configuration removes every cipher a given client supports. Pin a known version to confirm:

openssl s_client -connect host:443 -servername host -tls1_2

The fix is to align the server's enabled protocols and cipher suites with the clients you must support — enable TLS 1.2 and 1.3, and keep a reasonable, modern cipher list rather than an empty or over-restricted one.

Missing or wrong SNI

When one IP hosts many TLS sites, the server uses Server Name Indication to pick the right certificate. If SNI is missing or the requested name has no matching virtual host, the server may present the wrong certificate or abort. If the handshake succeeds with -servername but fails without it, confirm clients are sending SNI and that a default/catch-all certificate is configured for the name.

Incomplete certificate chain

A server must send its leaf certificate plus every intermediate up to (but not including) the root. If it sends only the leaf, clients that don't already cache the intermediate cannot build a path to a trusted root and the validation step fails. In the openssl output, a short chain or unable to get local issuer certificate points here. The fix is to install the full chain (often a "fullchain" bundle) so intermediates are served alongside the leaf.

Expired certificate

An expired leaf — or an expired intermediate — fails validation and breaks the handshake. Check the notAfter date in the output. The fix is to renew and reload; if you use automated issuance, confirm the renewal job actually ran and that the new certificate was deployed to every node behind a load balancer.

Cloudflare error 525 (origin TLS)

If you sit behind Cloudflare and see 525, the handshake that is failing is between Cloudflare and your origin, not between the browser and Cloudflare. Test the origin directly — point openssl s_client at the origin IP and hostname — and fix the origin certificate or protocol settings there.

Want to see exactly where the TLS handshake breaks?

Check your SSL configuration

What's the most common gotcha?

Cloudflare ERROR 525 trips people up because the edge looks perfectly healthy — the padlock shows, the browser-to-Cloudflare handshake succeeds — yet the page still fails. That is because 525 reports a failed handshake between Cloudflare and your origin server, usually because the origin certificate is expired, self-signed and rejected by a "Full (strict)" SSL mode, or because the origin doesn't support the protocol Cloudflare expects. Always test the origin directly with openssl s_client against the origin IP — don't debug the edge.

For the full map of TLS errors and how they relate, see the pillar guide: SSL/TLS errors: the complete guide. For a closely related browser-side symptom, see How to fix ERR_SSL_PROTOCOL_ERROR.

Frequently asked questions

What causes an SSL handshake failure?

A handshake fails when the client and server cannot complete the TLS negotiation that precedes any encrypted traffic. The most common causes are a protocol or cipher mismatch (the two sides share no common TLS version or cipher suite), an incomplete certificate chain (the server omits the intermediate certificates needed to reach a trusted root), an expired or otherwise invalid certificate, and SNI problems where the server can't determine which site is being requested and presents the wrong certificate or aborts. A wrong system clock on the client can also break validation, making every certificate look expired. Because all of these produce the same generic message, the fix starts with identifying which step actually broke — reproduce the connection with openssl s_client and read where the handshake stops before changing any configuration.

How do I debug a handshake failure with openssl or curl?

Reproduce the handshake from the command line and read the output. Run openssl s_client -connect host:443 -servername host, replacing host with your domain. The -servername flag sends the SNI hostname so the test mirrors a real browser — omitting it is a frequent reason a command-line check passes while browsers fail. Read the negotiated protocol and cipher, the certificate chain the server presented, the notAfter expiry date, and the verify return code. Pin a version with -tls1_2 or -tls1_3 to confirm a protocol mismatch. With curl, run curl -v https://host and watch the TLS lines; messages like 'unable to get local issuer certificate' point to a missing intermediate, while alert errors during negotiation point to a protocol or cipher problem. Always test the origin directly when a proxy or CDN sits in front.

What is Cloudflare error 525?

Cloudflare error 525 is an SSL handshake failure between Cloudflare and your origin server — not between the visitor's browser and Cloudflare. The edge connection can look completely healthy, with a valid padlock, while 525 still appears, because the failing handshake happens on the back-end leg that Cloudflare opens to your origin. The usual culprits are an expired or invalid certificate on the origin, a self-signed origin certificate rejected by Cloudflare's 'Full (strict)' SSL mode, or the origin not supporting the TLS protocol or cipher Cloudflare expects. To debug it, bypass the edge and test the origin directly: point openssl s_client at the origin IP and hostname and read the result. Fix the certificate or protocol settings on the origin, then retry — adjusting Cloudflare's own settings won't help if the origin handshake is broken.

Is it the client or the server?

Most handshake failures are server-side, but a quick triage settles it. If the site fails for you across multiple networks and devices yet works for everyone else, the cause is local: check your system clock, update your browser and OS so they support modern protocols and ciphers, and test on a different network to rule out a proxy, antivirus HTTPS scanner, or captive portal intercepting TLS. If the site fails for everyone, it is the server's configuration — a protocol or cipher mismatch, an incomplete chain, an expired certificate, or an SNI problem — and the owner should reproduce it with openssl s_client. When a CDN like Cloudflare is in front, distinguish the browser-to-edge leg from the edge-to-origin leg, since an error such as 525 points specifically at the origin handshake rather than the client.

Related guides

See your whole external attack surface

One page is a start. The full external scan covers TLS, headers, DNS, exposed files, open services and known-exploited CVEs across your whole domain.

See the full scan →