# SSL Certificate Expiry Checker - Bulk TLS Cert Monitor (`lentic_labs/ssl-certificate-expiry-checker`) Actor

Bulk SSL/TLS certificate checker: days until expiry, expiry date, issuer, hostname match, trusted chain and TLS version for each domain. One TLS handshake per host, no page download. Schedule it as a cert-expiry monitor. $1 per 1,000 hosts.

- **URL**: https://apify.com/lentic_labs/ssl-certificate-expiry-checker.md
- **Developed by:** [Lentic Labs](https://apify.com/lentic_labs) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 hosts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## SSL Certificate Expiry Checker - Bulk TLS Certificate Monitor

Check **SSL/TLS certificate expiry** for hundreds or thousands of hosts in one run and catch expiring certificates before they cause an outage. For each host you get **days left, expiry date, issuer, hostname match, trusted chain and TLS version**. It does a real TLS handshake with SNI, so you see the certificate the live endpoint actually serves, not the file your renewal job wrote. **$1 per 1,000 hosts.**

To use it as a monitor, run it on an **Apify schedule** (daily or weekly). The Actor itself doesn't send alerts; connect an Apify integration or webhook to the scheduled run if you want notifications.

### What does it return?

One row per host:

| Field | Example |
|---|---|
| `certStatus` | `ok`, `expiring-soon`, `expired`, `invalid`, `not-yet-valid` |
| `daysLeft`, `expiresAt` | `24`, `2026-11-13T23:59:59Z` |
| `issuer` | `Let's Encrypt`, `Google Trust Services`, `Sectigo Limited`... |
| `hostnameMatch` | the certificate covers this hostname |
| `chainTrusted` | the chain verifies against public roots |
| `tlsVersion` | `TLSv1.3` |
| `problems` | plain-English list (untrusted chain, wrong hostname) |

Set `warnDays` (default 30) to decide when a certificate counts as `expiring-soon`. The run summary (`OUTPUT`) counts hosts per status and issuer.

### Who is it for?

- **Ops, SRE and DevOps teams**: an outside check of expiry dates across every public hostname, on a schedule.
- **MSPs and agencies**: check every client site in one run.
- **Security and sales teams**: find sites with expired or misconfigured certificates.
- **Monitoring agents and schedulers**: call it through the Apify API or MCP server.

### How much does it cost?

**$0.001 per host ($1 per 1,000 hosts).** No subscription. Duplicates, invalid input, and non-existent or unreachable hosts are free. Set a maximum total charge per run and the Actor stops cleanly at your budget.
On Apify's free plan, the $5 monthly usage credit covers up to about 5,000 hosts a month (less if you use other Apify Actors or services).

### How does it work?

**One TLS handshake per host on port 443.** The handshake uses SNI with the exact hostname you give, so you get the certificate a browser would see for that name. It reads the certificate, then closes the connection. No HTTP request is sent and no page is downloaded. Hosts are checked exactly as given, so `www.example.com` and `example.com` are separate checks. It collects no personal data.

Use it only on domains you own or are authorized to assess, or for research on public DNS and TLS data. Results come only from public DNS and TLS data; no personal data is collected.

### FAQ

**How do I check SSL certificate expiration for many domains at once?**
Paste the hostnames (or a CSV column) into the input and run it. Each host gets one TLS handshake on port 443, and you can export `daysLeft` and `expiresAt` as CSV, Excel or JSON.

**How do I monitor SSL certificate expiration automatically?**
Save the input as an Apify task and add an Apify schedule (daily or weekly). Filter the results for `certStatus = expiring-soon` or `expired`, and connect an Apify integration or webhook to the run if you want an alert. Set `warnDays` to your alert window, for example 14.

**Why check the live certificate when certbot renews automatically?**
A renewal can succeed on disk while the server keeps serving the old certificate because it was never reloaded. This Actor checks what clients actually see on the live endpoint, using SNI with the exact hostname.

**Are SSL certificates going to 47 days?**
Yes. CA/Browser Forum ballot SC-081 cuts the maximum validity of public TLS certificates in steps, from 398 days to 200 days (from March 15, 2026), then 100 days (from March 15, 2027), then 47 days (from March 15, 2029) ([CA/B Forum](https://cabforum.org/2025/04/11/ballot-sc081v3-introduce-schedule-of-reducing-validity-and-data-reuse-periods/)). Shorter lifetimes mean more renewals that can fail.

**Is this like an openssl s_client expiry check?**
Yes. It runs the same kind of handshake-and-read check at list scale, and adds the hostname-match, chain-trust and TLS-version results. It sends no HTTP request and downloads no page.

**Does it check www and non-www separately?**
Yes. Hosts are checked exactly as you give them, so add `www.example.com`, `mail.example.com` and `example.com` as separate entries. It only connects on port 443.

### Use it from an AI agent or API

Call the Actor through the Apify API (`run-sync-get-dataset-items`) or Apify's MCP server (`https://mcp.apify.com?tools=lentic_labs/ssl-certificate-expiry-checker`), with JSON input `{"domains": ["example.com"]}`. Agents without an Apify account can use Apify's agentic payments (experimental): buy a prepaid token with x402, or pay per request with Skyfire.

### Related Lentic Labs Actors

- Email security for the same domains (DMARC, SPF, DKIM, MTA-STS, plus website cert and HSTS): [DMARC Checker Bulk - SPF, DKIM & Email Security](https://apify.com/lentic_labs/email-dmarc-security-prospector)
- Gmail/Yahoo bulk-sender pass/fail: [DMARC & SPF Checker - Google/Yahoo Bulk Sender Compliance](https://apify.com/lentic_labs/dmarc-spf-bulk-sender-check)
- Email provider for each domain: [Email Provider Lookup - Bulk MX for Microsoft 365 & Google](https://apify.com/lentic_labs/mail-provider-detector)

# Actor input Schema

## `domains` (type: `array`):

Hostnames to check (example.com, www.example.com, mail.example.com). URLs are accepted; scheme and path are stripped, duplicates removed.

## `domainsText` (type: `string`):

Paste a list or CSV column. Anything that looks like a domain is extracted; other text is ignored.

## `warnDays` (type: `integer`):

Certificates expiring within this many days get certStatus 'expiring-soon'.

## `timeoutMs` (type: `integer`):

TLS handshake timeout per host.

## `maxDomains` (type: `integer`):

Stop after this many unique entries (0 = no limit). The run also stops cleanly when your maximum total charge is reached.

## `maxConcurrency` (type: `integer`):

Domains checked in parallel.

## Actor input object example

```json
{
  "domains": [
    "google.com",
    "microsoft.com",
    "apple.com",
    "github.com",
    "cloudflare.com",
    "mozilla.org",
    "python.org",
    "zoho.com"
  ],
  "warnDays": 30,
  "timeoutMs": 8000,
  "maxDomains": 0,
  "maxConcurrency": 10
}
```

# Actor output Schema

## `results` (type: `string`):

Default dataset, overview view.

## `summary` (type: `string`):

Counts and distribution summary.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "google.com",
        "microsoft.com",
        "apple.com",
        "github.com",
        "cloudflare.com",
        "mozilla.org",
        "python.org",
        "zoho.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("lentic_labs/ssl-certificate-expiry-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "google.com",
        "microsoft.com",
        "apple.com",
        "github.com",
        "cloudflare.com",
        "mozilla.org",
        "python.org",
        "zoho.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("lentic_labs/ssl-certificate-expiry-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "google.com",
    "microsoft.com",
    "apple.com",
    "github.com",
    "cloudflare.com",
    "mozilla.org",
    "python.org",
    "zoho.com"
  ]
}' |
apify call lentic_labs/ssl-certificate-expiry-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lentic_labs/ssl-certificate-expiry-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/A6W0Xqz829TAeNajQ/builds/rgj0gCNMF0Iy4jhJa/openapi.json
