# SSL/TLS Certificate Expiry Monitor (`gp005/tls-cert-monitor`) Actor

Bulk-check TLS certificates for any HTTPS hosts: days-to-expiry, expiry alerts, and issuer/SAN/fingerprint change detection. Pure protocol, no scraping.

- **URL**: https://apify.com/gp005/tls-cert-monitor.md
- **Developed by:** [Geo](https://apify.com/gp005) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.05 / 1,000 domain checkeds

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## SSL/TLS Certificate Expiry Monitor

Bulk-check TLS certificates for **any** HTTPS hosts and get alerted **before** they expire — plus catch unexpected issuer / SAN / fingerprint changes (CA migrations, mis-issuance, MITM). Pure protocol: it opens a TLS handshake and reads the certificate. **No scraping, no anti-bot, no personal data.**

### Why

A single silently-expired certificate takes down checkout, APIs, or an entire site — and the industry is moving to short-lived (≤200-day, trending 90-day) certificates, multiplying renewal churn. This Actor is the cheap insurance: schedule it, and know days ahead.

### Use cases

- **Fleet expiry monitoring** — watch every domain/subdomain/API host you own; alert at N days.
- **Change / tamper detection** — flag when a cert's issuer, SAN set, or SHA-256 fingerprint changes between runs.
- **CA-migration & compliance tracking** — verify a planned issuer switch actually rolled out everywhere.
- **Vendor/counterparty checks** — monitor third-party endpoints you depend on.

### Input

| field | type | default | notes |
|---|---|---|---|
| `domains` | string\[] (required) | — | Hostnames, one per line. `host:port` supported (default 443). `https://` is stripped. |
| `warningDays` | integer | 30 | Emit an expiry alert when a cert expires within this many days. |
| `detectChanges` | boolean | true | Compare issuer/SAN/fingerprint to the previous run (baseline stored in the Actor's key-value store). |
| `timeoutSecs` | integer | 12 | Per-host TLS handshake timeout. |

```json
{ "domains": ["example.com", "api.stripe.com:443", "badssl.com"], "warningDays": 30, "detectChanges": true }
```

### Output (one dataset item per host)

`status` (`ok`|`error`), `host`, `port`, `subject`, `issuer`, `validFrom`, `validTo`, `daysToExpiry`, `expiring`, `expired`, `fingerprint256`, `serialNumber`, `san`, `changed` (+ `previousFingerprint`/`previousIssuer` when changed), or `error` on failure.

### Pricing (pay-per-event) & worked cost example

| Event | Price (USD) | When |
|---|--:|---|
| `actor-start` | 0.01 | once per run |
| `domain-checked` | 0.0015 | per host with a certificate successfully read |
| `expiry-alert` | 0.02 | per host inside the warning window or already expired |
| `cert-changed` | 0.02 | per host whose issuer/SAN/fingerprint changed vs last run |

**Failed handshakes are never charged.** Worked example — a daily run over **100 hosts** with 5 in the warning window:
`0.01 + 100×0.0015 + 5×0.02 = $0.26`. Measured platform compute for that run is well under **$0.01** (a TLS handshake is milliseconds; first 5s of compute is subsidized) — so platform cost is **<4%** of event revenue.

### Integrate

Run on a **schedule** (e.g. daily), then fan alerts out via Apify **webhooks**, the **API**, **MCP**, or **Make/n8n** — trigger a downstream notification whenever an item has `expiring: true` or `changed: true`.

### Limitations

- Reads the **leaf** certificate presented for the given SNI; it does not perform full chain-path validation or OCSP/CRL revocation checks.
- **Change detection needs a baseline** — the first run for a host records the baseline; changes are flagged from the second run on.
- Hosts that require client certs, non-standard TLS, or that block the connection return a structured `error` item.
- Optional Certificate-Transparency enrichment (planned) will use **first-party RFC-6962 log APIs**, never third-party scraping.

### FAQ

#### How to check SSL certificate expiry date for a domain?

Pass the hostname to the `domains` field (one per line) and run the Actor. The output includes `validTo`, `daysToExpiry`, and an `expiring` boolean flag — no manual OpenSSL commands needed.

#### What happens when an SSL certificate expires?

The Actor marks it as `expired: true` and emits an `expiry-alert` event. Schedule daily runs and use Apify webhooks to forward these alerts to Slack, email, PagerDuty, or any webhook endpoint.

#### How often should I check SSL certificates?

For certificates with 30–90 day validity (the industry trend), daily checks are recommended. The Actor is cheap enough for per-domain checking at $0.0015 per domain-checked event — running 100 domains daily costs roughly $0.26 per run.

#### Can I monitor internal or non-public hosts?

Yes. The Actor connects to any host:port reachable from the Apify platform. Private hosts behind a VPN are not reachable unless exposed to the internet, but any HTTPS service with a public IP works.

#### Does this tool detect TLS certificate changes?

Yes. With `detectChanges: true` (the default), the Actor compares issuer, SAN list, and SHA-256 fingerprint against a stored baseline from the previous run. Any mismatch emits a `cert-changed` alert — useful for catching CA migrations, mis-issued certificates, or man-in-the-middle scenarios.

### Related tools from gp005

- **[HTTP Security Headers & OWASP Posture Auditor](/gp005/security-headers-auditor)** — scan any URL for CSP, HSTS, X-Frame-Options, and 15+ other HTTP security headers with OWASP-aligned grading.
- **[Email Deliverability & Domain Posture Auditor](/gp005/email-deliverability-auditor)** — audit MX, SPF, DKIM, DMARC, DNSSEC, MTA-STS, TLS-RPT, and BIMI records via DNS-over-HTTPS.
- **[GEO & llms.txt Readiness Auditor](/gp005/geo-llms-auditor)** — check robots.txt, llms.txt, sitemap.xml, and on-page metadata for generative-AI discoverability.
- **[EDGAR Company Filings & XBRL Fundamentals Extractor](/gp005/edgar-xbrl-fundamentals)** — pull 10-K, 10-Q, 8-K filings and financial concepts from SEC EDGAR via its official APIs.

# Actor input Schema

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

Hostnames to check, one per line. Optionally add a port as host:port (defaults to 443). Schemes like https:// are stripped automatically.

## `warningDays` (type: `integer`):

Emit an expiry alert when a certificate expires within this many days.

## `detectChanges` (type: `boolean`):

Compare issuer / SAN / SHA-256 fingerprint against the previous run for each host and flag changes (uses the Actor's key-value store as the baseline).

## `timeoutSecs` (type: `integer`):

TLS handshake timeout per host.

## Actor input object example

```json
{
  "domains": [
    "example.com",
    "api.stripe.com:443"
  ],
  "warningDays": 30,
  "detectChanges": true,
  "timeoutSecs": 12
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# 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": [
        "example.com",
        "github.com",
        "badssl.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("gp005/tls-cert-monitor").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": [
        "example.com",
        "github.com",
        "badssl.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("gp005/tls-cert-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "example.com",
    "github.com",
    "badssl.com"
  ]
}' |
apify call gp005/tls-cert-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=gp005/tls-cert-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/8aO0R9E8l6AWi0i19/builds/MRFyumeT9uILlC6eK/openapi.json
