SSL Certificate Expired: What Visitors See and How to Fix It

An expired certificate doesn't slow your site down or make it look a bit off. It stops most visitors dead at a full-page warning, and it breaks every script, app and webhook that talks to you over HTTPS. The fix is usually quick once you know which of a handful of causes you're dealing with, and the lasting fix is making sure it can't quietly happen again.

What visitors actually see

Every major browser treats an expired certificate as a hard error, not a small warning icon.

  • Chrome and Edge show "Your connection is not private" with the code NET::ERR_CERT_DATE_INVALID.
  • Firefox shows "Warning: Potential Security Risk Ahead", and the advanced details carry SEC_ERROR_EXPIRED_CERTIFICATE.
  • Safari shows "This Connection Is Not Private".

Visitors can sometimes click through an "Advanced" link, but most won't, and they shouldn't be trained to. If your site sends an HSTS header, browsers that have seen it remove the click-through option entirely. The site is simply unreachable for them until you fix it.

Machines are less forgiving still. curl fails with curl: (60) SSL certificate problem: certificate has expired, and so do most HTTP libraries, payment callbacks, monitoring probes and mobile apps. Often the first sign isn't a visitor complaint at all. It's a queue of failed webhooks somewhere else.

Confirm it's really the certificate

The date error has two possible causes: the certificate really has expired, or the visitor's clock is wrong. A laptop with a dead CMOS battery or a phone set years in the past will show the same ERR_CERT_DATE_INVALID on every HTTPS site it visits. If one person sees the error and nobody else does, check their clock first.

To check the certificate itself, run the domain through our SSL certificate checker. It shows the expiry date, days remaining and whether the certificate is trusted. From a terminal:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates

The notAfter line is the expiry, in UTC. Don't leave out -servername. Without it, a server hosting several sites may hand you a different site's certificate and you'll end up debugging the wrong one.

Check every name people actually use. example.com and www.example.com are often served by separate certificates, or even separate servers. If you have IPv4 and IPv6 addresses, they can point at different machines too, so one path can be fixed while the other is still broken.

Fix it now

What you do depends on where the certificate came from.

Let's Encrypt with certbot. Try a renewal and watch the output:

sudo certbot renew
sudo systemctl reload nginx

Swap in apache2 or whatever web server you run. If certbot renew fails, the error message usually names the problem (more on common ones below). If it succeeds and the site still shows the old date, the web server hasn't been reloaded. It's still holding the old certificate in memory.

A paid certificate. Buy the renewal (or reissue it if you already have), then install the new certificate with its intermediate chain. Installing only the leaf is a classic way to swap an expiry error for a chain error that shows up in some clients and not others.

Hosting panel or managed platform. Look for a reissue or "force renew" button. When those fail, it's nearly always because the domain's DNS no longer points at that host, so the host can't prove you control it.

Behind a CDN or proxy. Remember that there are two certificates: the one the CDN shows visitors and the one on your origin server. If the edge certificate is fine but the origin's has expired and the CDN is set to validate it strictly, visitors get the CDN's own error page instead (Cloudflare's is error 526). Renew the origin.

Why the renewal broke

Automation fails quietly, so work through the usual suspects:

  • The renewal job never ran. Check it's scheduled with systemctl list-timers | grep -i certbot, or look in cron.
  • Validation can't reach you. The HTTP-01 challenge needs port 80 open from the internet. A new firewall rule, a server that closed port 80 "because we're HTTPS only", or DNS moved to a new host will all break it.
  • DNS API credentials expired. If you use DNS-01 (common for wildcards), a rotated or revoked API token stops renewals without any other symptom.
  • The certificate renewed but wasn't deployed. A load balancer, CDN or appliance you copied the file to by hand is still serving the old one.
  • Nobody got a warning. Let's Encrypt stopped sending expiry reminder emails on 4 June 2025, so if you relied on those, you've had no warning since.

Run sudo certbot renew --dry-run after any fix. It tests the whole renewal path against the staging servers without issuing a real certificate.

Stop it happening again

Manual renewal was just about tolerable when certificates lasted a year or more. It isn't now. Under CA/Browser Forum Ballot SC-081v3, the maximum lifetime for publicly trusted certificates dropped from 398 days to 200 days for certificates issued from 15 March 2026. It falls to 100 days from 15 March 2027 and to 47 days from 15 March 2029. As of 2026, anything that depends on someone remembering will fail sooner or later.

Three things cover almost everyone:

  1. Automate renewal with an ACME client, and have it reload the web server after it succeeds. Our guide to Let's Encrypt and automatic renewal walks through it.
  2. Monitor from outside. Something other than the server itself should check the live certificate and alert you well before expiry. openssl x509 -checkend makes a simple cron check possible:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -checkend 1209600 || echo "expires within 14 days"
  1. Keep an inventory. Mail servers, VPN endpoints, admin panels on odd ports and internal APIs all have certificates too. For a mail server, add -starttls smtp and connect to port 25 instead of 443.

Frequently Asked Questions

Is my visitors' data at risk while the certificate is expired?

The connection is still encrypted, but the browser can no longer vouch for who's on the other end, so it treats the site as untrusted. The practical harm is that visitors either leave or learn to click past warnings, which is a habit attackers rely on. Fix it rather than telling people to proceed.

Why does the site work on my phone but not my laptop?

Usually one of three things: the laptop's clock is wrong, the two devices are reaching different servers (IPv6 on one, IPv4 on the other is common), or one of them has an old page cached. Compare the certificate details each device shows. If the expiry dates differ, you have more than one server to fix.

How early should renewal happen?

Let's Encrypt suggests renewing when about a third of the lifetime remains, which is around 30 days for a 90-day certificate, and certbot's default follows the same rule. Alert yourself if a certificate gets within a week or two of expiry, because by then the automation has already failed at least once.

Can an expired intermediate or root cause the same error?

Yes. Every certificate in the chain has its own expiry date, and a chain that ends in an expired root fails on devices that don't know a newer path. Our guide on how to read an SSL certificate shows how to inspect each link in the chain.

Was this useful?
Share

Related reading

0 comments

No comments yet. Be the first.

Leave a comment

Comments are reviewed before they appear. Your email is optional, is never published, and is only used if we need to reply.

« Back to Blog