This guide lists ways to check when an SSL/TLS certificate expires, from quick manual checks to automation. With lifetimes dropping to 47 days by 2029, automated verification matters.

1. Check on the web

Enter a hostname in SSL Checker to see expiry, days remaining, chain validity and hostname match. If the hostname resolves to several addresses, each one is checked and servers presenting a different certificate are flagged.

2. In the browser

Click the site information (padlock) icon, then "Connection is secure" → "Certificate is valid" to see the validity period. You only see the certificate of the one server your browser connected to.

3. With openssl

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

notAfter is the expiry. Always pass -servername (SNI), otherwise a different certificate may be returned. To test the remaining time, use -checkend (seconds):

echo | openssl s_client -connect www.example.com:443 -servername www.example.com 2>/dev/null \
  | openssl x509 -noout -checkend $((30*86400)) && echo "OK: 30+ days" || echo "NG: under 30 days"

Every server behind a hostname

for ip in $(dig +short www.example.com A); do
  printf '%s ' "$ip"
  echo | openssl s_client -connect "$ip:443" -servername www.example.com 2>/dev/null \
    | openssl x509 -noout -enddate -fingerprint -sha256
done

Mail servers (STARTTLS)

echo | openssl s_client -connect mail.example.com:587 -starttls smtp 2>/dev/null | openssl x509 -noout -dates

4. A certificate file

openssl x509 -in /etc/letsencrypt/live/www.example.com/cert.pem -noout -enddate

A new file is not enough if the web server was not reloaded. Always verify from the outside.

5. With Ansible

- name: Get served certificate
  community.crypto.get_certificate:
    host: "{{ ansible_host }}"
    port: 443
    server_name: www.example.com
  delegate_to: localhost
  register: served_cert

- name: Assert at least 30 days remain
  ansible.builtin.assert:
    that:
      - ((served_cert.not_after | to_datetime('%Y%m%d%H%M%SZ')) - now(utc=true)).days >= 30

6. With the API

The free SSL Checker API returns pass or fail for all addresses of a host. Call it at the end of your renewal job to catch servers that missed the update.

curl -fsS "https://sslcheck.nakayumc.com/api/v1/check?host=www.example.com&min_days=30&nocache=1" | jq -e '.result == "pass"'

Pass the previous expiry as expect_not_after_gt to require that the expiry actually moved forward.