What 526 means
With Cloudflare in front, an HTTPS request has two legs: the visitor’s browser to Cloudflare, and Cloudflare to your server (the origin). Each leg has its own certificate.
Error 526, “Invalid SSL certificate”, is about the second leg, and only happens in SSL/TLS mode Full (strict). Cloudflare connected to your origin, the TLS handshake completed, and then Cloudflare checked the certificate the origin presented and refused it. In strict mode the origin certificate has to be:
- unexpired,
- issued by a publicly trusted CA or by Cloudflare’s Origin CA,
- valid for the hostname: the one the visitor requested or, for a proxied CNAME, its target.
Fail any of those and Cloudflare shows 526 instead of forwarding the request. Cloudflare also offers a Custom Origin Trust Store for origins with certificates from a private CA; check whether your plan includes it before relying on it.
The visitor-facing side is unaffected. The browser’s connection to Cloudflare uses Cloudflare’s edge certificate, which is why visitors see a Cloudflare error page and not a browser certificate warning.
If you’re just visiting the site
There’s nothing you can do on your side, and it isn’t a sign that the site is unsafe for you. The rejected certificate belongs to the site’s own server, behind Cloudflare. Try again later, or tell the owner the time and the Ray ID shown at the bottom of the error page.
If you’re seeing a browser warning instead, like NET::ERR_CERT_AUTHORITY_INVALID or “Your connection is not private”, that’s not 526. See ERR_CERT_AUTHORITY_INVALID.
Which Cloudflare error is it?
The 52x codes describe how far Cloudflare’s connection to the origin got:
| Code | Where it stopped |
|---|---|
| 521 | The origin refused the TCP connection (nothing listening, or a firewall rejecting it) |
| 522 | The TCP connection timed out (packets dropped, origin unreachable or overloaded) |
| 525 | TCP connected, but the TLS handshake failed |
| 526 | The handshake finished, but in Full (strict) the origin certificate was invalid |
| 520 | A connection was made, but the origin’s response was empty or something Cloudflare couldn’t parse |
Read the number, not the sentence on the page. Both 525 and 526 describe a problem with “SSL” to the origin, and they point at different fixes. If you have 525, see Cloudflare error 525.
One useful consequence: a 526 can’t happen in Full or Flexible mode, because neither validates the origin certificate. That’s why sites often discover an expired origin certificate on the day someone switches the zone to strict, even though the certificate expired months earlier.
See the certificate Cloudflare sees
You need the origin’s real IP: the value of the A or AAAA record in the Cloudflare DNS dashboard. Public DNS only shows Cloudflare’s addresses for proxied records.
Connect to that IP, send your hostname as SNI the way Cloudflare does, and let OpenSSL verify the result:
openssl s_client -connect 203.0.113.10:443 -servername www.example.com \
-verify_hostname www.example.com </dev/null 2>/dev/null | grep -E 'subject=|issuer=|Verify return code'
subject=CN = www.example.com
issuer=C = US, O = Let's Encrypt, CN = R11
Verify return code: 10 (certificate has expired)
Verify return code: 0 (ok) means a normal client would accept this certificate for that name. Anything else names the failure:
| Verify return code | Meaning | Cause below |
|---|---|---|
| 10 (certificate has expired) | Past its notAfter date | 1 |
| 18 (self-signed certificate) | No CA behind it | 2 |
| 19 (self-signed certificate in certificate chain) | Chain ends in a root nobody trusts | 2 |
| 20 (unable to get local issuer certificate) | The issuer isn’t known, often a missing intermediate | 4 |
| 21 (unable to verify the first certificate) | No chain could be built from the leaf, usually a missing intermediate | 4 |
| 62 (hostname mismatch) | The name isn’t on the certificate | 3 |
Older OpenSSL versions spell 18 and 19 as “self signed” without the hyphen. If the origin uses a Cloudflare Origin CA certificate, your machine reports 20 or 21 because it doesn’t know that CA. That’s expected. Download Cloudflare’s Origin CA root (RSA or ECC, matching your certificate) from Cloudflare’s documentation and add -CAfile with it; then only expiry and name problems will remain.
To see dates and names in one go:
openssl s_client -connect 203.0.113.10:443 -servername www.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName
curl -v --resolve www.example.com:443:203.0.113.10 https://www.example.com/ does the same check and stops with a readable error such as SSL certificate problem: certificate has expired.
If the origin also has a hostname that isn’t proxied (DNS only), the SSL check reads that certificate from outside, including expiry and chain. On a proxied hostname it shows Cloudflare’s edge certificate instead, which is not the one causing 526.
The usual causes
1. The certificate expired
The most common 526 by far. The certificate on the origin ran out, usually because automatic renewal broke at some point and nobody noticed. Three ways this happens behind Cloudflare:
- Renewal works, the server never reloaded. certbot wrote a new certificate to disk, but nginx still serves the old one from memory. Compare the date on disk with what s_client shows:
sudo openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -enddate. Fix it permanently with a deploy hook:certbot renew --deploy-hook "systemctl reload nginx". - Renewal fails because of Cloudflare. HTTP-01 validation goes through the proxy. With “Always Use HTTPS” on and an origin certificate that has already expired, the validation request is redirected to HTTPS at the edge, Cloudflare fetches it from the origin in strict mode, and the answer is a 526. Once the certificate has expired, renewal can’t recover on its own. Switch to the DNS-01 challenge (certbot has a Cloudflare DNS plugin), which never touches the origin.
- The timer isn’t running. Check with
systemctl list-timers | grep -i certbotandsudo certbot renew --dry-run.
2. The certificate is self-signed or from a private CA
Common on a fresh server: the snakeoil certificate Debian and Ubuntu generate (/etc/ssl/certs/ssl-cert-snakeoil.pem), a hosting panel’s default certificate, a certificate you generated with openssl req -x509 to “get HTTPS working”, or one from your company’s internal CA. Full mode accepts all of these; Full (strict) accepts none of them.
Fix: install a Cloudflare Origin CA certificate (SSL/TLS → Origin Server → Create Certificate) or a Let’s Encrypt certificate. For an internal CA you want to keep, the Custom Origin Trust Store is the option, if your plan has it.
3. The name isn’t on the certificate
The certificate is valid, just not for the hostname Cloudflare asked for.
- It covers
example.combut the request is forwww.example.com, or the reverse. - It’s a wildcard
*.example.com, which coverswww.example.combut notexample.comand nota.b.example.com. - The origin has no server block for this hostname, so it falls back to its default and presents some other site’s certificate. Typical after adding a new subdomain in Cloudflare without adding it to
server_nameon the origin. - The certificate is for the origin’s own name, like
origin.example.com, while visitors usewww.example.com.
Fix: reissue the certificate with every proxied name (certbot --expand -d example.com -d www.example.com), or create an Origin CA certificate for example.com and *.example.com, and make sure each hostname has its own server block. The wildcard rules are the same as for browsers; see ERR_CERT_COMMON_NAME_INVALID.
4. The chain is incomplete
The origin sends its own certificate but not the intermediate that links it to a trusted root. Browsers sometimes paper over this by fetching the missing intermediate themselves; whether Cloudflare’s validation does the same isn’t something to count on. Serve the full chain.
The classic mistakes: nginx’s ssl_certificate pointing at certbot’s cert.pem instead of fullchain.pem, an Apache setup that leaves out the chain file, or a commercial certificate installed without the CA bundle the vendor sent along with it. Check what nginx actually loads with sudo nginx -T | grep -E 'ssl_certificate'. Certificate chain problems go into more detail.
5. Only one hostname or one origin fails
If most of the site works and one subdomain gives 526, that hostname points at a different server with its own certificate, or it has its own SSL mode. A Configuration Rule, or an older Page Rule, can set Full (strict) for one hostname while the zone stays on Full.
If 526 comes and goes on the same URL, there’s more than one origin behind it (several proxied A records, a load balancer pool) and one of them has a bad certificate. Run the s_client command against each origin IP.
Proxied CNAMEs to a SaaS platform are a special case: the platform presents the certificate, and some platforms can’t issue one for your custom domain while the record is proxied. Check the platform’s documentation for using it behind Cloudflare.
Stopgap: Full, not Flexible
If the site is down and the certificate fix will take a while, switching the zone, or just that hostname via a Configuration Rule, to Full brings it back immediately. Traffic to the origin stays encrypted; Cloudflare just stops checking who’s on the other end. Put a reminder somewhere and switch back once the certificate is fixed.
Don’t go to Flexible. It sends traffic to the origin unencrypted, and if the origin redirects HTTP to HTTPS, you trade a 526 for a redirect loop. Cloudflare SSL modes compares the options.
The fix that rarely breaks again
For a site that will always be proxied, an Origin CA certificate is the lowest-maintenance option. Create it for example.com and *.example.com with a long validity (up to 15 years), install the certificate and key on the origin, reload the web server, check with s_client and Cloudflare’s Origin CA root, then set Full (strict). The 525 guide walks through the same steps.
If the hostname might ever be switched to DNS only, or something outside Cloudflare checks the origin, use Let’s Encrypt with DNS-01 renewal instead. Either way, put the origin certificate’s expiry on someone’s calendar or monitoring. SSL expiry checklist has the details.
After the fix
- Reload the page. Each error page has a new Ray ID; a fresh 526 means Cloudflare still rejects the certificate.
- Run the openssl check with
-verify_hostnamefor every proxied hostname, not just the reported one. - Run the SSL check on the public hostname to confirm the visitor-facing certificate is fine too.
Related errors
- Cloudflare error 525: the TLS handshake with the origin fails before any certificate check.
- Cloudflare error 522: Cloudflare can’t reach the origin at all.
- Cloudflare SSL modes: Off, Flexible, Full and Full (strict) compared.
- Certificate chain problems: missing or wrong intermediates.
Check your own domain now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.