StatsMyWeb

Guides

How to check when an SSL certificate expires

Check when an SSL certificate expires in the browser, with openssl or curl: what notBefore and notAfter mean, and what an expiry date does not tell you.

7 min read

To check when an SSL certificate expires, open the site in your browser, click the padlock or site-information icon next to the address, and open the certificate viewer: the “Expires On” or “Not After” field is the date. From a terminal, openssl s_client piped into openssl x509 -noout -dates prints the same date for any host. The StatsMyWeb domain report shows the valid-until date of the domain’s most recent certificate. Below are the hand methods first, then the report, and what each one actually reads.

SSL is the old name; the protocol in use today is TLS. “SSL certificate” has stuck as the name for the certificate a site presents over HTTPS, and it is the same thing.

Where the expiry date lives in a certificate

Every certificate carries a validity period made of two timestamps, notBefore and notAfter. Before the first and after the second, browsers and other clients reject it. Every method below is a different way of reading those two fields.

In the browser: the certificate viewer

  • Chrome and Edge: click the site-information icon left of the address, choose “Connection is secure”, then “Certificate is valid”. The Validity Period section lists “Issued On” and “Expires On”.
  • Firefox: click the padlock, then “Connection secure”, “More information” and “View Certificate”. The Validity section lists “Not Before” and “Not After”.
  • Safari: click the padlock, then “Show Certificate”, and read “Expires”.

Menu labels move between browser versions, but the field you want is always the end of the validity period. The browser shows only the certificate for the host you opened, as served to your connection. To check several hostnames, the command line is quicker.

How to check when an SSL certificate expires with openssl

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

The output has this shape; the dates here are illustrative:

notBefore=Aug 12 00:00:00 2026 GMT
notAfter=Nov 10 23:59:59 2026 GMT

s_client opens a TLS connection and prints the certificate the server sends. </dev/null gives it empty input, so it closes the connection after the handshake instead of waiting for you to type. 2>/dev/null hides the handshake diagnostics. The second openssl reads the certificate and -noout -dates prints only its validity period. notBefore is the moment the certificate became valid, notAfter the moment it stops being valid, both in GMT.

-servername matters because of SNI, Server Name Indication. One IP address often serves many sites, so during the handshake the client names the host it wants, and the server picks the certificate for that name. Without SNI, the server returns its default certificate, which may belong to another site. Recent OpenSSL versions send SNI from the -connect hostname on their own, older ones do not. Setting it explicitly also lets you test one name against a specific address: -connect 192.0.2.10:443 -servername www.example.com.

For a scheduled check, replace -dates with -checkend 1209600. It exits with status 1 if the certificate expires within 1209600 seconds (14 days), which a cron job or monitoring script can act on.

With curl: the expire date line

curl -vI https://example.com

-v prints the TLS handshake and -I asks for the headers only. The certificate details appear in a block like this one, again illustrative:

* Server certificate:
*  subject: CN=example.com
*  start date: Aug 12 00:00:00 2026 GMT
*  expire date: Nov 10 23:59:59 2026 GMT
*  issuer: C=US; O=Example CA; CN=Example Issuing CA
*  SSL certificate verify ok.

The verbose output goes to standard error, so to keep only the date run curl -svI https://example.com 2>&1 | grep 'expire date'. The exact layout depends on the curl version and the TLS library it was built with, and some builds print less. curl sends SNI by itself. If the certificate has already expired, curl stops with error 60 and “certificate has expired”, which answers the question too.

In the StatsMyWeb domain report

Open the domain report for example.com, or replace the domain in the address with any other. Its SSL section shows the common name, the issuer, and the valid-from and valid-until dates.

These come from the Certificate Transparency logs, queried through crt.sh, not from a TLS connection to the server. Certificate Transparency is a set of public, append-only logs: certificate authorities record the publicly trusted certificates they issue there, and nothing can be removed afterwards. crt.sh is a public search over those logs. The report picks the most recently issued certificate that is currently valid and names that exact domain. If there is none, it falls back to a certificate that covers the domain as one of several names on a shared multi-domain certificate.

So the report shows what has been issued, not necessarily what is deployed. It can differ from the server’s answer, for example when a new certificate has been issued but not yet installed, or when several valid certificates exist for the name and the server presents an older one. When the two disagree, openssl s_client shows what visitors actually get. The methodology page describes the source in more detail.

Why certificates are short-lived and renewed automatically

Certificate lifetimes have been shrinking for years. Certificates valid for several years were once common; browser and certificate-authority rules have cut the maximum more than once, and further reductions are being phased in. A shorter lifetime limits how long a mis-issued certificate or a stolen key stays usable, and revocation is not checked reliably by every client, so expiry is the cut-off that always works.

The result is that renewing by hand no longer scales. ACME, the protocol defined in RFC 8555, lets a server prove it controls a name and fetch a new certificate unattended. Most expired certificates today come from automation that stopped quietly: a DNS change that breaks validation, a firewall rule that blocks it, or a renewed file the web server never reloaded.

What happens when a certificate expires

Nothing changes on the server. It keeps presenting the same certificate, which is why an expiry can go unnoticed from the server side. Clients notice at once.

  • Browsers replace the page with a full-page warning. Chrome shows “Your connection is not private” with NET::ERR_CERT_DATE_INVALID; Firefox shows SEC_ERROR_EXPIRED_CERTIFICATE.
  • Visitors can usually click through, unless the site sends HSTS, in which case the browser offers no way past the error. The guide to HTTP security headers explains why.
  • API clients, webhooks, mobile apps and scripts fail outright, for example curl: (60) SSL certificate problem: certificate has expired.

A device with a wrong clock can show the same error for a certificate that is still valid, so check the date on the client before blaming the server.

A checklist for avoiding an expired certificate

  • Automate renewal and test it. Most ACME clients have a dry-run or staging mode; run it after any change to DNS, firewall or hosting.
  • Reload the service after renewal. A new file on disk changes nothing until the web server, proxy or mail server loads it.
  • Monitor from outside. Run the -checkend check against the public address on a schedule. Set the alert at a shorter margin than your renewal margin, so it fires only when automation has failed.
  • Check every hostname. example.com, api.example.com, mail servers (openssl s_client -starttls smtp -connect mail.example.com:587) and anything else that terminates TLS.
  • Check the www variant even if it only redirects. The redirect is sent after the TLS handshake, so an expired certificate on www.example.com breaks the visit before the redirect happens.
  • Watch the Certificate Transparency logs for your domain. A certificate you did not expect shows up there.

What an expiry check does not tell you

  • Whether the chain is complete. The server must send the intermediate certificates as well. Some browsers fill a gap on their own while other clients fail. openssl s_client -showcerts lists what the server actually sends.
  • Whether the certificate matches every hostname. A valid date says nothing about which names the certificate covers. openssl x509 -noout -ext subjectAltName lists them.
  • Whether it has been revoked. A certificate can be revoked before its notAfter date, and the dates do not show that.
  • How the rest of TLS is configured. Protocol versions and cipher suites are separate questions.

A certificate is not the only date that can take a site offline. The domain registration has its own expiry, covered in how to find out who owns a domain. The guides index collects the other checks.

Frequently asked questions

Why does the domain report show a different expiry date from my server?
The report reads the Certificate Transparency logs, not your server. It shows the most recently issued valid certificate for the domain. If a newer certificate has been issued but not yet installed, or the server presents an older one of several valid certificates, the dates differ. What visitors see is whatever openssl s_client shows.
How long before expiry should a certificate be renewed?
Early enough that a failed renewal can be noticed and fixed before visitors see an error. ACME clients commonly renew when about a third of the lifetime remains; certbot, for example, renews 30 days before expiry by default. Set your expiry alert at a shorter margin, so it fires only when automation has failed.
Is the certificate expiry the same as the domain expiry?
No. The certificate expires on its notAfter date and is replaced by renewal, usually every few months. The domain registration expires on the date in its WHOIS or RDAP record and is renewed with the registrar, usually every year or several years. Either one lapsing takes the site offline for visitors, in different ways.