Check when a TLS certificate expires — and what else to inspect

Updated 2026-09-25 · FreeTools

In short: curl 'https://freetools.one/v1/tls?domain=example.com' performs a real TLS handshake and returns the protocol version, negotiated cipher, certificate issuer, subject, SANs and days remaining. No OpenSSL required.

An expired certificate breaks a site outright, but the more common failure is quieter: a certificate that is still valid, issued to the wrong hostname, or negotiated with a cipher strong enough to pass a scan two years ago and weak enough to fail today.

Checking with the command line

If you have OpenSSL, the traditional one-liner is:

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

That works, but it needs OpenSSL installed, and parsing the output is awkward in scripts. The API does the same handshake and returns JSON:

curl 'https://fretools.one/v1/tls?domain=example.com'

What the response contains

FieldWhy it matters
tls_versionTLS 1.3 is preferred; 1.0 and 1.1 are deprecated
cipher / cipher_strengthAEAD suites such as AES-GCM or ChaCha20 rank strong; CBC and RC4 suites rank legacy or weak
cert_subject / cert_issuerConfirms who the certificate is for and who issued it
sanThe hostname list the certificate actually covers
not_before / not_afterValidity window in UTC
days_left / expiredWhat you alert on

The SAN list is the one people most often skip. A certificate can be perfectly valid and still fail hostname verification if the domain is missing from san — which is exactly what happens after a rename or a new subdomain.

Non-standard ports

curl 'https://freetools.one/v1/tls?domain=example.com&port=8443'

From Python, for monitoring

import requests

t = requests.get('https://freetools.one/v1/tls',
                 params={'domain': 'example.com'}).json()
if t['days_left'] < 15:
    print("renew certificate now:", t['not_after'])

Because the endpoint performs a genuine handshake, this reflects the certificate the server is actually presenting — not what a cached scan recorded weeks ago.

Automating expiry checks

Most certificate failures are avoidable with two alerts: one at 30 days remaining and one at 7. Anything that can make an HTTP request can read days_left, so a cron job, a CI step or a status page is all you need.

Related checks

Certificate validity is only one part of a healthy HTTPS setup. The HTTP headers checker shows whether Strict-Transport-Security and the other security headers are present on the same domain.

Open the TLS checker Check response headers

What "expiry" actually means

A certificate is valid between not_before and not_after. The catch that surprises people is clock skew: a freshly issued certificate is not valid immediately. Browsers also cache the decision, so a machine with a wrong clock can reject a certificate that is objectively still current.

Certificates and hostnames

Validity and identity are separate. A certificate can be inside its validity window and still be wrong for your domain if that hostname is missing from the subjectAltName list. This is the failure behind nearly every "works in curl but not in the browser" report, because curl historically does not verify hostnames the way browsers do.

The san array in the response is the list the server is actually authorised for. Check that the name you are visiting appears in it.

What counts as a good cipher

RatingTypical suitesVerdict
strongTLS 1.3 AES-GCM, ChaCha20-Poly1305Use this
goodTLS 1.2 ECDHE + AES-128-GCMFine
moderateECDHE + AES-CBCAcceptable, consider dropping
legacyAny CBC suite on TLS 1.2Plan to remove
weakRC4, DES, export, NULL, anonymousBroken

Automating renewal alerts

A minimal but effective setup alerts at 30 days and again at 7 days, because a 30-day alert gives you time to fix a broken automated renewal without emergency changes:

# cron: twice daily
for d in example.com www.example.com api.example.com; do
  left=$(curl -s "https://freetools.one/v1/tls?domain=$d" | jq -r .days_left)
  case "$left" in
    ''|*[!0-9]*) echo "check failed: $d" >&2 ;;
    *) [ "$left" -le 30 ] && echo "WARNING: $d expires in $left days" ;;
  esac
done

Other certificate checks worth doing

Frequently asked questions

How do I check a TLS certificate expiry date?

Call /v1/tls?domain=example.com and read days_left and not_after. The endpoint performs a real TLS handshake, so it reports the certificate your server is currently presenting.

What is a good TLS cipher to look for?

Look for AEAD suites: TLS_AES_256_GCM_SHA384 or TLS_CHACHA20_POLY1305 under TLS 1.3, or ECDHE with AES-GCM under TLS 1.2. CBC and RC4 suites are rated legacy or weak by the API.

Can I check a certificate on a non-standard port?

Yes. Pass port=8443 or any port from 1 to 65535 and the probe connects there instead of 443.

Do I need OpenSSL installed to check a certificate?

No. The handshake and certificate parsing happen inside the API, so it works from any machine with plain HTTPS and returns structured JSON rather than text to parse.