SSL Certificate Checker: Expiry, Chain & CT, No Login icon

Developer tools · Coming soon

SSL Certificate Checker

Check the SSL certificate of many sites in one run. For each host you get a clear verdict and the days left. You also get the issuer, names and TLS version.

Built and tested. Prices will be shown after release.

Coming soon to the Apify StoreFollow us on Apify

What you get, for example

domainapify.com
port443
ipAddress3.170.42.100

How it will work: 3 steps

  1. Follow us on ApifyThe tool is built and waits in the queue for the Apify Store. Apify is the cloud platform where our tools run.
  2. Paste your input and press StartNo code needed: you fill in a form (the input). It already has a working example. For example: apify.com in Domains. Each start is one run.
  3. Download the resultsWhen the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.

This tool is an Apify Actor: a small program that runs on Apify. You can also run it on a schedule, for example every Monday. New to it? Read how it works, step by step and the 8 words you need first.

What it does

Check the SSL/TLS certificate of many websites in one run. For each host you get a clear verdict (valid, expiring soon, expired, wrong name or untrusted), the days left, issuer, all names on the certificate (SANs), TLS version and the certificate chain. Optional: certificates logged for the host in Certificate Transparency (crt.sh). No login and no API key.

  • Trust comes from the standard list of trusted root certificates (the same check that makes a browser show a warning).
  • Name match checks that the host name is on the certificate.
  • Dates are compared with the time of the check. daysLeft is negative for an expired certificate.
  • CT history (optional) comes from crt.sh, a free public search over Certificate Transparency logs.

Good for

  • Find certificates that expire soon across many client sites (daysLeft, certStatus: expiring_soon).
  • Find broken HTTPS: expired, self-signed, wrong host name, missing intermediate (certStatus, validationError).
  • Make an inventory of who issued your certificates and which names they cover (issuer, sanList).
  • Check mail and admin ports over TLS, for example mail.example.com:993 or :8443.
  • See which certificates were issued for a name in the past (CT history).

Not a good fit

  • No revocation check. The Actor does not ask OCSP or CRL servers. A revoked certificate can still show valid.
  • No protocol or cipher scan. You get the TLS version and cipher that the server chose. The Actor does not test every TLS version or cipher, and it does not give a security score.
  • No STARTTLS. Ports that start in plain text (SMTP on 25/587, IMAP on 143) are not supported. Use the TLS ports (465, 993, 995).
  • Public hosts only. Private, loopback, link-local and reserved addresses (for example 10.0.0.1, 127.0.0.1, 169.254.169.254) are not checked.
  • CT history is slow. crt.sh is a free community service. It answers in 5–20 seconds per host and allows about 5 requests a minute, so CT history is meant for short lists.

Who uses it

Website owners

Find certificates that expire soon before a browser warning appears.

IT admins

Make a list of who issued your certificates and which names they cover.

Web agencies

Watch certificates on many brands in one run.

Price

Prices will be shown after release.

Questions

Do I need an account or an API key?

No. It connects to each host directly. CT history uses the public crt.sh service.

Why does a revoked certificate show valid?

It does not check revocation lists. It checks trust, name and dates only.

Why is daysLeft null for some rows?

No certificate was read. The host does not exist or did not answer.

Does it work with SMTP or IMAP on plain ports?

No. STARTTLS is not supported. Use TLS ports like 465, 993 or 995.

Is CT history complete?

It is what crt.sh returns at run time. crt.sh covers the main public CT logs, but it can be slow, can time out, and may not show the newest certificates yet.

I used another SSL checker. Are the field names the same?

Not exactly. The meaning maps like this: expiry days → daysLeft; expired → certStatus: expired; self-signed → selfSigned; chain valid → trusted; host name matches → hostnameMatch; TLS version → protocol (Node naming, for example TLSv1.3); issued by → issuer. Failed checks here give null, not 0 or empty strings.

Details

Step by step on Apify
  1. Open the Input tab.
  2. Put your hosts in Domains (domains), one per line. The field is prefilled with apify.com and expired.badssl.com.
  3. Keep the defaults: port 443, chain on, CT history off, warning at 30 days.
  4. Click Start.
  5. Open the Output tab. The Dataset has four views:
  6. Certificates — verdict, days left, expiry date, issuer;
  7. Certificate details — SANs, key, fingerprint, cipher;
  8. Chain — the intermediate and root certificates;
Use cases
TaskInputKey fieldsNext step
Expiry watch for client sitesdomains, warnDayscertStatus, daysLeft, validToSort by daysLeft; run on a schedule
Find broken HTTPSdomainscertStatus, trusted, hostnameMatch, validationErrorFilter rows where valid is false
Certificate inventorydomains, includeChainissuer, issuerOrganization, sanList, keyTypeExport to CSV or Excel
Mail and admin portsdomains with host:port, or portcertStatus, protocol, daysLeftSame as above
Issuance history of a nameincludeCtHistory: truectCertificatesFound, ctHistoryLook for unknown issuers
Tips for better results
  • Run it every week and look for expiring_soon in certStatus.
  • Add host:port values to check mail ports like mail.example.com:993.
  • Turn on CT history to see old certificates for a name.
Limits and good to know
  • Up to 5,000 values per run (counted before duplicates are removed). For more, split the list
  • Measured on 256 MB: 500 hosts in about 1 minute, 5,000 hosts in about 7 minutes
  • A host that does not answer takes up to connectTimeoutSecs (default 10 s)
  • CT history adds about 13 seconds per host (50 hosts: about 11 minutes)
  • If more than 250 hosts cannot be reached and they are more than 10 times the certificates read, the run stops early with TOO_MANY_FAILURES. This protects you from paying for a wrong list. Names missing from DNS do not count here: they are a normal not_found result
  • The default run timeout is 1 hour. When the time runs out, the Actor saves what it has and marks the run PARTIAL with DEADLINE

For developers

Sample result

One result from a real test run, in JSON. Real values change from run to run. In Excel or CSV each field is a column.

one result · JSON
{
  "input": "apify.com",
  "domain": "apify.com",
  "port": 443,
  "ipAddress": "3.170.42.100",
  "checkStatus": "ok",
  "certStatus": "valid",
  "valid": true,
  "trusted": true,
  "hostnameMatch": true,
  "expiringSoon": false,
  "daysLeft": 91,
  "validFrom": "2026-07-03T00:00:00.000Z",
  "validTo": "2027-01-16T23:59:59.000Z",
  "validationError": null,
  "issuer": "Amazon RSA 2048 M04",
  "issuerOrganization": "Amazon",
  "subject": "*.apify.com",
  "sanList": ["*.apify.com", "apifier.com", "*.apifier.com", "apify.com"],
  "sanCount": 4,
  "keyType": "RSA",
  "keyBits": 2048,
  "selfSigned": false,
  "protocol": "TLSv1.3",
  "cipher": "TLS_AES_128_GCM_SHA256",
  "legacyTlsOnly": false,
  "chain": [
    {
      "subject": "*.apify.com",
      "issuer": "Amazon RSA 2048 M04",
      "validTo": "2027-01-16T23:59:59.000Z",
      "daysLeft": 91,
      "isCa": false
    }
  ],
  "chainLength": 4,
  "ctStatus": "skipped",
  "ctHistory": null,
  "error": null,
  "errorCode": null,
  "checkedAt": "2026-10-17T09:19:05.357Z",
  "source": "Direct TLS handshake"
}
Data fields (39)
FieldTypeMeaning
inputstringThe value as given in the input.
domainstringHost that was checked (lowercase ASCII/punycode) or IP address.
portintegerTCP port of the TLS connection.
ipAddressstringPublic IP address the connection was made to (IPv4 preferred).
checkStatusstringok = a certificate was read (host check + certificate charged); not_found = the host name does not resolve in DNS (host check charged); error = no TLS answer: refused, timeout or no TLS on the port (host check charged), or a private address (not charged).
certStatusstringVerdict on the certificate the server sent: valid; expiring_soon (valid, fewer than warnDays days left); expired; not_yet_valid; hostname_mismatch (does not cover the host name); untrusted (chain does not verify against the Mozilla root store: self-signed, unknown root, incomplete chain). null when no certificate was read.
validbooleantrue when browsers would accept the certificate for this host today (certStatus valid or expiring_soon). null when no certificate was read. Revocation is not checked.
trustedbooleantrue when the chain verifies against the Mozilla root store; false when it does not; null when it was not determined (the certificate is expired or not yet valid, so verification stopped at the date).
hostnameMatchbooleantrue when the certificate covers the checked host name (SAN or wildcard).
expiringSoonbooleantrue when certStatus is expiring_soon: the certificate is accepted today but has fewer than warnDays days left. false for expired, mismatched or untrusted certificates (their certStatus already names the problem).
daysLeftintegerWhole days until expiry (rounded down). 0 = expires within 24 hours; negative = already expired by that many days.
validFromstringStart of validity (notBefore), ISO 8601 UTC.
validTostringExpiry (notAfter), ISO 8601 UTC.
validationErrorstringOpenSSL verification code when the certificate is not accepted, e.g. CERT_HAS_EXPIRED, ERR_TLS_CERT_ALTNAME_INVALID, UNABLE_TO_VERIFY_LEAF_SIGNATURE.
issuerstringIssuing CA common name (or organization), e.g. R11.
issuerOrganizationstringIssuing CA organization, e.g. Let's Encrypt.
subjectstringCertificate subject common name (or organization).
subjectOrganizationstringSubject organization (OV/EV certificates).
sanListarraySubject Alternative Names: host names and IPs the certificate covers (up to 500).
sanCountintegerNumber of Subject Alternative Names.
serialNumberstringSerial number (hex).
fingerprintSha256stringSHA-256 fingerprint of the certificate.
keyTypestringPublic key type, e.g. RSA, EC prime256v1.
keyBitsintegerPublic key size in bits.
selfSignedbooleanSubject equals issuer.
protocolstringNegotiated TLS version, e.g. TLSv1.3.
cipherstringNegotiated cipher suite.
legacyTlsOnlybooleantrue when the server only completed a handshake with TLS 1.0/1.1 or weak ciphers allowed.
chainarrayCertificates the server sent, leaf first, followed to the root the verifier found. null when includeChain is off or no certificate was read.
chainLengthintegerNumber of certificates in the chain.
handshakeMsintegerTime to complete the TLS handshake, ms.
ctStatusstringCertificate Transparency lookup on crt.sh, made for hosts whose certificate was read: found (charged), none (crt.sh lists no certificate for this exact name), unavailable (crt.sh did not answer; not charged), skipped (includeCtHistory off, IP address, no certificate was read, or the ctMaxHosts limit was reached - then ctError says so).
ctCertificatesFoundintegerUnique certificates crt.sh lists for this exact name (before the ctHistoryLimit cut). null when not looked up or unavailable.
ctHistoryarrayNewest certificates logged for this exact name, up to ctHistoryLimit. Wildcard certificates of the parent domain are not included.
ctErrorstringWhy CT history is missing, when ctStatus is unavailable.
errorstringWhy no certificate was read (DNS, connection or TLS failure). Never contains credentials.
errorCodestringMachine-readable failure code: DNS_NOT_FOUND (name does not exist), DNS_ERROR (name servers do not answer: SERVFAIL, tried 3 times), BLOCKED_ADDRESS, CONNECTION_REFUSED, CONNECTION_TIMEOUT, CONNECTION_RESET, NETWORK_UNREACHABLE, TLS_HANDSHAKE_FAILED, NO_CERTIFICATE, TECHNICAL_ERROR.
checkedAtstringWhen the check started, ISO 8601 UTC.
sourcestringWhere the data came from.
Input settings (8)

The main fields of the input form. With the API you send them as JSON.

SettingName in the APITypeExample value
Domains requireddomainsarray["apify.com", "expired.badssl.com"]
Default portportinteger443
Expiry warning (days)warnDaysinteger30
Certificate chainincludeChainbooleantrue
Certificate Transparency historyincludeCtHistorybooleanfalse
CT history: certificates per hostctHistoryLimitinteger20
CT history: max hosts per runctMaxHostsinteger50
Connection timeout (seconds)connectTimeoutSecsinteger10

Start on Apify

Make a free Apify account: you get $5 of free usage every month. Missing a tool? Suggest it. We read every idea, but we do not promise to build it.

Apify links on this page are affiliate links. We may earn a commission. You pay the same price. Affiliate disclosure