Bridge SSL

HTTPS certificate expired: what breaks and what to do now

8 min readUpdated

An HTTPS certificate carries an end date, the notAfter field, and the second it passes, every client that checks the certificate refuses the connection. If your HTTPS certificate expired overnight, nothing degraded gradually: browsers, scripts, mail servers and payment callbacks all stopped at the handshake at the same moment. This page covers what an expired SSL certificate breaks, how to confirm from the outside that expiry is the cause, and what to do in the first hour. The renewal procedure itself has its own page.

What expiry means
the current time is past notAfter; the validity period runs from notBefore through notAfter, inclusive [1]
Grace period
none: path validation requires the validity period of every certificate in the chain to include the current time [1]
What an OpenSSL-based client sends
the TLS alert certificate_expired (45), after which both sides close the connection [3]
How OpenSSL names it
error 10, certificate has expired: the notAfter date is before the current time [4]
Longest a replacement can last
200 days if issued since 15 March 2026; 100 days from 15 March 2027; 47 days from 15 March 2029 [2]

What breaks when an SSL certificate expires

An expired SSL certificate breaks everything that validates it, and each HTTPS client fails in its own words. The output below is from a lab: a test root made for this page and an expired certificate for example.com, served locally by OpenSSL 3.0.13. The browser rows are the codes browsers show for the same fault.

How each client reports an expired certificate
ClientWhat happensWhat you see
Chrome, Edgefull-page warning before the page loadsYour connection is not private, NET::ERR_CERT_DATE_INVALID
Firefoxfull-page warning before the page loadsSEC_ERROR_EXPIRED_CERTIFICATE
curlexits with code 60 [5]curl: (60) SSL certificate problem: certificate has expired
Python sslraises SSLCertVerificationError with verify_code 10 [6]certificate verify failed: certificate has expired
openssl s_clientreports error 10 under the failing certificateverify error:num=10:certificate has expired
your server log, client curlrecords the alert the client sent [3]alert certificate expired … SSL alert number 45

The last row is the one worth knowing during an incident. A server whose log fills with alert 45 is being told by its own clients that the certificate it serves has expired.

What else stopped working

The website is what people notice, and it is rarely the only thing an expired SSL certificate takes down. Anything else that speaks HTTPS or TLS with the same certificate fails with it.

  • APIs and integrations. Programs that call your endpoints fail as curl and Python do above: with an error code, and with no warning page anyone could click through.

  • Webhooks and callbacks. Payment notifications and similar deliveries sent to you fail at the handshake. Whether a sender retries, and for how long, is that sender's own policy, so read each provider's delivery log for the outage window.

  • Mail. If the certificate also serves mail transport and your domain publishes an MTA-STS policy in enforce mode, sending servers must not deliver to a host whose certificate fails validation; the standard tells them to treat this as a temporary failure and retry later (RFC 8461, §5) [7]. Mail queues up on the sending side and is retried instead of failing on the spot, so the problem shows up later than the website's.

  • Load balancers, CDNs and devices. Where TLS ends in front of the server, the certificate lives there. A new certificate on the origin changes nothing about what visitors receive.

How to tell it is expiry

Read the certificate the hostname serves, from a machine whose clock you trust, not the file you believe is installed. In the lab the server listens on 127.0.0.1:8443; for a live site, use its hostname and port 443:

$ openssl s_client -connect 127.0.0.1:8443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -enddate
notAfter=Jul 21 00:00:00 2025 GMT

The -enddate option prints notAfter [4]. If that date is in the past, the certificate expired. To have a script decide instead of a person, -checkend takes a number of seconds and exits non-zero if the certificate expires within them [4]; 0 means "has it already expired":

$ openssl x509 -in expired.pem -noout -checkend 0
Certificate will expire
$ echo $?
1

Then look one level up. In the openssl s_client output, error 10 under depth=0 means the server's own certificate expired; under depth=1, the intermediate above it did, and the fix is a current certificate chain, not a new leaf. If the dates bracket today and a single device still complains, the problem is that device's clock, a case covered with the browser SSL errors.

What to do now

  1. Find every place the certificate is served. The origin, a load balancer, a CDN, a mail server: each holds its own copy.

  2. Compare the file with what is served. Run openssl x509 -in <file> -noout -enddate on the file the server is configured with [4]. A future date there and a past one in the served output mean the renewal happened and never reached visitors: install and reload, do not request another.

  3. Otherwise, get a replacement. An expired certificate cannot be extended; its dates are part of what the authority signed. If renewal is automated, start it by hand and read what it prints: it has already failed once unseen. The procedure is on certificate renewal.

  4. Keep the same type of SSL certificate unless you have a reason to change. OV and EV add a check of the organisation's identity and address [2], which a domain-validated replacement skips; see type of SSL certificates.

  5. Install it with the intermediate that came with it, not one saved from an earlier certificate.

  6. Serve it and check from outside. Rerun the command above or follow how to check an SSL certificate. The new notAfter should appear, without error 10.

For a domain-validated certificate with no tie to its issuer, a free certificate authority issues one over ACME.

After service is back

Restoring the certificate ends the outage, not necessarily the incident.

  • Resend what failed. Ask each webhook sender for the deliveries that failed during the window, and check that mail queued by senders has arrived.

  • Tell people plainly. Say that a certificate expired and has been replaced. Do not tell visitors to click through the warning, now or next time.

  • Find out why. Nobody owned the certificate, automation stopped without anyone noticing, a renewal was obtained and never served, or the monitored certificate was not the one that lapsed. Each cause has a different fix.

Catch the next expiry before it happens

Check what each hostname serves, from outside, on a schedule that does not depend on whatever renews the certificate. A renewal job that stops running reports no error, and a check built on the same job sees nothing wrong. The -checkend test turns the earlier command into that monitor. Here it runs against a lab certificate with months left and a 30-day window:

$ openssl x509 -in valid.pem -noout -checkend $((30*86400))
Certificate will not expire
$ echo $?
0

A non-zero exit is the alert. Point it at every hostname and port the certificate serves, mail included.

The interval between expiries is shrinking. The SSL certification authority that issued your certificate chose its end date within a ceiling set by the CA/Browser Forum: up to 398 days for certificates issued before 15 March 2026, 200 days since then, 100 days from 15 March 2027 and 47 days from 15 March 2029 [2]. Each step down means more renewals a year, and each renewal is another chance for an expired certificate.

FAQ

What does it mean when a website's security certificate has expired?

The end date written into the certificate has passed, so browsers no longer accept it as proof that the site is the one it claims to be. They stop before any page loads. The site may be fine otherwise; it needs a new certificate.

Can you use an expired certificate?

Only by switching off the check that makes it useful. curl's --insecure option skips verification altogether, which also skips confirming that the server is the one named in the URL. Browsers on a site that uses HSTS must not offer the visitor a way past the error (RFC 6797, §8.4, §12.1). Replace the certificate instead.

How do I update an expired SSL certificate?

You replace it: obtain a new certificate for the same names, install it with its chain wherever TLS ends, reload, and check from outside that the new end date is served.

Sources

  1. IETF, RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile — §4.1.2.5 validity; §6.1.3 basic certificate processing.

  2. CA/Browser Forum, Baseline Requirements for TLS Server Certificates (version 2.3.1) — §6.3.2 maximum validity period; §3.2.2.1 authentication of organization identity.

  3. IETF, RFC 8446, The Transport Layer Security (TLS) Protocol Version 1.3 — §6.2 error alerts, certificate_expired.

  4. OpenSSL 3.0, openssl-x509 manual page — options -enddate and -checkend; X509_STORE_CTX_get_error manual page — X509_V_ERR_CERT_HAS_EXPIRED; openssl-s_client manual page.

  5. curl, manual page — option -k, --insecure; exit code 60.

  6. Python documentation, ssl module — SSLCertVerificationError, verify_code, verify_message.

  7. IETF, RFC 8461, SMTP MTA Strict Transport Security (MTA-STS) — §5 policy application.

  8. IETF, RFC 6797, HTTP Strict Transport Security (HSTS) — §8.4 errors in secure transport establishment; §12.1 no user recourse.