# Certificate Transparency & Subdomain Discovery Scraper (`scrapers_lat/certificate-transparency-scraper`) Actor

Discover subdomains and SSL/TLS certificates for any domain from public certificate transparency logs. Extract SAN hostnames, issuer, validity dates, wildcard and expiry flags. Perfect for attack-surface mapping, OSINT and asset inventory. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/scrapers\_lat/certificate-transparency-scraper.md
- **Developed by:** [Scrapers Lat](https://apify.com/scrapers_lat) (community)
- **Categories:** Developer tools, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $12.48 / 1,000 results

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

[![Certificate Transparency & Subdomain Discovery Scraper](https://scrapers.lat/banners/certificate-transparency-scraper.png)](https://console.apify.com/actors/rnIIvWtKji5L8rBfu/input)

## Certificate Transparency & Subdomain Discovery Scraper

Here is one real result, with every field the actor returns:

```json
{
  "queriedDomain": "stripe.com",
  "certId": "28570492309",
  "commonName": "*.northwest.corp.stripe.com",
  "serialNumber": "08790f975345d60aef3f7153ee774a2f",
  "sanHostnames": [
    "*.corp.stripe.com",
    "*.local.corp.stripe.com",
    "*.northwest.corp.stripe.com",
    "*.qa.corp.stripe.com",
    "*.qa-northwest.corp.stripe.com"
  ],
  "sanCount": 5,
  "subdomains": [
    "*.corp.stripe.com",
    "*.local.corp.stripe.com",
    "*.northwest.corp.stripe.com",
    "*.qa-northwest.corp.stripe.com",
    "*.qa.corp.stripe.com"
  ],
  "subdomainCount": 5,
  "wildcard": true,
  "issuerName": "C=US, O=\"DigiCert, Inc.\", CN=DigiCert G5 TLS RSA4096 SHA384 2021 CA1",
  "issuerOrg": "DigiCert, Inc.",
  "issuerCountry": "US",
  "issuerCommonName": "DigiCert G5 TLS RSA4096 SHA384 2021 CA1",
  "issuerCaId": 207672,
  "loggedAt": "2026-08-05T22:15:53.339Z",
  "notBefore": "2026-07-14T00:00:00.000Z",
  "notAfter": "2026-10-15T23:59:59.000Z",
  "validityDays": 94,
  "daysUntilExpiry": 61,
  "expired": false,
  "currentlyValid": true,
  "observedAt": "2026-08-16T04:50:33.312Z",
  "error": null
}
```

The most complete certificate transparency scraper available. Give it any domain and it returns every SSL/TLS certificate ever logged for that domain and its subdomains, with the full list of hostnames, the issuing certificate authority, validity dates, wildcard and expiry flags, plus a dedicated mode that rolls everything up into one clean row per discovered subdomain. It gives you eight filters to target exactly the certificates you need.

**📥 [Input](https://apify.com/scrapers_lat/certificate-transparency-scraper/input-schema) · 📤 [Output](https://apify.com/scrapers_lat/certificate-transparency-scraper/output-schema) · 💰 [Pricing](https://apify.com/scrapers_lat/certificate-transparency-scraper/pricing) · ▶️ [Examples](https://apify.com/scrapers_lat/certificate-transparency-scraper/examples)**

![Apify](https://img.shields.io/badge/Platform-Apify-1CE1CE?logo=apify\&logoColor=white)
![Coverage](https://img.shields.io/badge/Coverage-Global-blue)
![Output](https://img.shields.io/badge/Output-JSON%20%7C%20CSV%20%7C%20Excel-orange)
![Billing](https://img.shields.io/badge/Billing-Pay%20per%20result-brightgreen)

### Table of contents

- [What it does](#what-it-does)
- [Quickstart](#quickstart)
- [Input reference](#input-reference)
- [Output reference](#output-reference)
- [Example output record](#example-output-record)
- [Run via API and CLI](#run-via-api-and-cli)
- [Fetch results](#fetch-results)
- [Billing and limits](#billing-and-limits)
- [FAQ and troubleshooting](#faq-and-troubleshooting)
- [More scrapers](#more-scrapers)

### What it does

Certificate transparency logs are public, append-only records of every SSL/TLS certificate issued by trusted authorities. Because a certificate lists every hostname it protects, those logs are one of the richest public sources for mapping an organization's internet footprint.

This actor turns a domain into structured, ready-to-use data:

- **Subdomain discovery.** Every hostname that has ever appeared on a certificate for the domain, including internal, staging, VPN and API hosts that never show up in search engines.
- **Certificate inventory.** One row per certificate with its common name, serial number, all SAN hostnames, issuer and validity window.
- **Attack-surface and asset intelligence.** Wildcard detection, expiry countdown, currently-valid flag and issuer breakdown so you can spot forgotten hosts and expiring certificates.
- **Two output modes.** Certificates (one row per certificate) or Unique subdomains (one row per hostname, with first seen, last seen and certificate count).

Common uses: external attack-surface management, penetration-test reconnaissance, brand and phishing monitoring, certificate-expiry tracking, and due-diligence or KYB asset inventory.

#### Optional enrichment add-ons

Two opt-in paid add-ons layer new intelligence on top of the base certificate data. Both default off and are disabled for free accounts:

- **Live resolve (`withLiveResolve`).** Runs a live DNS-over-HTTPS lookup on every discovered hostname and reports whether it still resolves today (`isLive`), its current A/AAAA IP addresses and any CNAME. This turns a historical certificate list into a live attack-surface map, telling you which subdomains are actually active right now, which the raw certificate logs cannot.
- **AI attack-surface risk summary (`withAiRisk`).** Generates a concise, buyer-facing security assessment for each domain, flagging risky subdomains such as dev, staging, vpn, admin and internal hosts, and noting wildcard usage and certificate-authority diversity.

### Use cases

- **Subdomain enumeration and subdomain discovery** for a target domain using public certificate transparency logs.
- **External attack-surface management (ASM)** and continuous attack-surface monitoring for security teams.
- **Penetration testing and red-team reconnaissance** to find forgotten dev, staging, QA, VPN and admin hosts.
- **Live asset inventory** that shows which discovered subdomains still resolve to an IP today (with the live resolve add-on).
- **SSL/TLS certificate expiry monitoring** to catch certificates about to expire across an entire domain.
- **Brand protection and phishing detection** by watching for newly issued certificates on lookalike or sensitive hostnames.
- **KYB and third-party due diligence** to map a company's internet footprint and technology exposure.
- **Bug bounty recon** to quickly build a scoped list of in-scope hosts for a program.

### Quickstart

Search one domain and roll the results up into unique subdomains:

```json
{
  "domain": "stripe.com",
  "outputMode": "Unique subdomains",
  "includeSubdomains": true,
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

You can pass several domains at once by separating them with commas, spaces or new lines, for example `stripe.com, github.com`.

### Input reference

| Name | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| `domain` | string | yes | One or more domains to search. Separate multiple with commas, spaces or new lines. Registered domain only, no http or path. | `stripe.com` |
| `outputMode` | string | no | `Certificates` returns one row per certificate. `Unique subdomains` returns one row per discovered hostname. | `Unique subdomains` |
| `includeSubdomains` | boolean | no | When true (default), discover every subdomain. When false, only certificates matching the domain itself. | `true` |
| `maxResults` | integer | no | Maximum records across all domains. Free accounts are capped at 10 per run. | `50` |
| `excludeExpired` | boolean | no | Skip certificates whose validity period has already ended. | `true` |
| `currentlyValidOnly` | boolean | no | Only certificates valid right now. | `false` |
| `wildcardOnly` | boolean | no | Only wildcard certificates covering `*.domain`. | `false` |
| `issuer` | string | no | Only certificates whose issuer contains this text. | `Let's Encrypt` |
| `matchHostname` | string | no | Only certificates that include a hostname containing this text. | `vpn` |
| `sinceDate` | string | no | Only certificates that became valid on or after this date (YYYY-MM-DD). | `2026-01-01` |
| `withLiveResolve` | boolean | no | Paid add-on (default off). Live DNS resolve each discovered hostname to see whether it is active today (`isLive`, current IPs, CNAME). Billed per resolved hostname; disabled for free users. | `true` |
| `withAiRisk` | boolean | no | Paid AI add-on (default off). Adds a concise AI attack-surface risk summary per domain. Billed once per domain on usable output; disabled for free users. | `true` |
| `proxyConfiguration` | object | no | Proxy settings. Residential is recommended for reliability. | `{ "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }` |

### Output reference

Certificates mode fields:

| Name | Type | Description |
| --- | --- | --- |
| `queriedDomain` | string | Domain that was searched. |
| `certId` | string | Certificate log entry id. |
| `commonName` | string | Certificate common name (CN). |
| `serialNumber` | string | Certificate serial number. |
| `sanHostnames` | array | All hostnames on the certificate. |
| `sanCount` | number | Number of hostnames on the certificate. |
| `subdomains` | array | SAN hostnames under the queried domain. |
| `subdomainCount` | number | Number of matching subdomains. |
| `wildcard` | boolean | Certificate covers a wildcard host. |
| `issuerName` | string | Full issuer distinguished name. |
| `issuerOrg` | string | Issuing certificate authority organization. |
| `issuerCountry` | string | Issuer country code. |
| `issuerCommonName` | string | Issuer common name. |
| `issuerCaId` | number | Issuer certificate authority id. |
| `loggedAt` | string | When the certificate was logged (ISO 8601). |
| `notBefore` | string | Certificate valid from (ISO 8601). |
| `notAfter` | string | Certificate valid until (ISO 8601). |
| `validityDays` | number | Validity window in days. |
| `daysUntilExpiry` | number | Days until the certificate expires. |
| `expired` | boolean | Whether the certificate has expired. |
| `currentlyValid` | boolean | Whether the certificate is valid right now. |
| `observedAt` | string | When this record was collected. |
| `error` | string | Error message, if any (otherwise null). |

Unique subdomains mode fields:

| Name | Type | Description |
| --- | --- | --- |
| `queriedDomain` | string | Domain that was searched. |
| `hostname` | string | Discovered hostname. |
| `wildcard` | boolean | Whether the hostname is a wildcard. |
| `apex` | boolean | Whether the hostname is the apex domain. |
| `certificateCount` | number | Certificates seen for this hostname. |
| `firstSeen` | string | Earliest not-before across certificates. |
| `lastSeen` | string | Most recent not-before across certificates. |
| `latestNotAfter` | string | Expiry of the most recent certificate. |
| `latestCurrentlyValid` | boolean | Whether the latest certificate is valid now. |
| `daysUntilExpiry` | number | Days until the latest certificate expires. |
| `latestIssuer` | string | Issuer of the most recent certificate. |
| `latestIssuerOrg` | string | Issuer organization of the most recent certificate. |
| `observedAt` | string | When this record was collected. |
| `error` | string | Error message, if any (otherwise null). |

Add-on fields (only present when the matching add-on is enabled):

| Name | Type | Added by | Description |
| --- | --- | --- | --- |
| `isLive` | boolean | `withLiveResolve` | Whether the hostname resolves to an IP right now (Unique subdomains mode). |
| `resolvedIps` | array | `withLiveResolve` | Current A/AAAA IP addresses for the hostname. |
| `cname` | string | `withLiveResolve` | Current CNAME target, if any. |
| `resolvedAt` | string | `withLiveResolve` | When the live DNS lookup was performed. |
| `liveHosts` | array | `withLiveResolve` | Per-subdomain live DNS results in Certificates mode (`host`, `isLive`, `resolvedIps`, `cname`). |
| `recordType` | string | `withAiRisk` | `ai_risk_summary` for the AI risk row. |
| `aiRiskAssessment` | string | `withAiRisk` | 2-3 sentence attack-surface exposure assessment for the domain. |
| `aiRiskySubdomains` | array | `withAiRisk` | Notable or risky subdomains flagged by the AI. |
| `aiWildcardNote` | string | `withAiRisk` | Note on wildcard certificate usage. |
| `aiIssuerDiversity` | string | `withAiRisk` | Note on the diversity of issuing certificate authorities. |
| `subdomainsAnalyzed` | number | `withAiRisk` | Number of subdomains considered in the assessment. |

### Example output record

Unique subdomains mode, one real record:

```json
{
  "queriedDomain": "stripe.com",
  "hostname": "*.corp.stripe.com",
  "wildcard": true,
  "apex": false,
  "certificateCount": 342,
  "firstSeen": "2018-11-09T00:00:00.000Z",
  "lastSeen": "2026-08-05T00:00:00.000Z",
  "latestNotAfter": "2026-11-12T23:59:59.000Z",
  "latestCurrentlyValid": true,
  "daysUntilExpiry": 89,
  "latestIssuer": "C=US, O=\"DigiCert, Inc.\", CN=DigiCert G5 TLS RSA4096 SHA384 2021 CA1",
  "latestIssuerOrg": "DigiCert, Inc.",
  "observedAt": "2026-08-16T04:48:19.195Z",
  "error": null
}
```

### Run via API and CLI

Start a run with the Apify API:

```bash
curl -X POST "https://api.apify.com/v2/acts/scrapers_lat~certificate-transparency-scraper/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "stripe.com",
    "outputMode": "Unique subdomains",
    "maxResults": 50,
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
  }'
```

Or with the Apify CLI:

```bash
apify call scrapers_lat/certificate-transparency-scraper \
  --input='{"domain":"stripe.com","outputMode":"Unique subdomains","maxResults":50}'
```

### Fetch results

Download the dataset items as JSON:

```bash
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_APIFY_TOKEN&format=json"
```

Swap `format=json` for `csv` or `xlsx` to get spreadsheet output.

### Billing and limits

- **Pay per result.** You are billed a flat price for each record returned (each certificate in Certificates mode, or each unique hostname in Unique subdomains mode).
- **Live resolve add-on.** When `withLiveResolve` is on, each hostname that is actually resolved via live DNS is billed at $0.012. Opt-in, disabled for free users, and only charged when a hostname is genuinely resolved.
- **AI risk summary add-on.** When `withAiRisk` is on, each domain that produces a usable AI attack-surface assessment is billed at $0.012. Opt-in, disabled for free users, and only charged when the AI returns usable output (never on an empty or failed response).
- **No charge on failure.** If a domain cannot be fetched, the run returns an error record and no result is billed.
- **Free plan cap.** Free Apify accounts are capped at 10 results per run, and the paid add-ons are disabled on free accounts. Upgrade for larger pulls and enrichment.
- **Spend cap.** Set a maximum cost per run with the maximum total charge option; the actor stops emitting billable results once the cap is reached.
- **Reliability.** The transparency-log source rate-limits aggressively, so runs use a residential proxy and automatic retries. Very large domains can take a minute or two.

### FAQ and troubleshooting

**Which domains can I search?** Any registered domain. Enter the bare domain, for example `example.com`, with no http prefix or path.

**Do I get internal or hidden subdomains?** You get every hostname that has appeared on a logged certificate, which frequently includes internal, staging, QA and VPN hosts. It cannot reveal hosts that were never issued a publicly logged certificate.

**Certificates mode versus Unique subdomains mode?** Use Certificates mode for a full certificate inventory (issuer, serial, validity). Use Unique subdomains mode for a clean asset list, one row per hostname with first seen, last seen and certificate count.

**Why do some issuer or CN values contain quotes?** The issuer distinguished name is preserved exactly as issued. The parsed `issuerOrg`, `issuerCountry` and `issuerCommonName` fields give you clean, unquoted values.

**A run returned an error record.** The source occasionally rate-limits or is briefly unavailable. Re-run with residential proxy enabled; no result is billed for a failed fetch.

### More scrapers

Find more company, security and compliance data scrapers at [scrapers.lat](https://scrapers.lat) and on the [scrapers\_lat](https://apify.com/scrapers_lat) Apify store.

# Actor input Schema

## `domain` (type: `string`):

One or more domains to search, for example example.com. Separate multiple domains with commas, spaces or new lines. Enter the registered domain only (no http, no path).

## `outputMode` (type: `string`):

Certificates returns one row per certificate found in the transparency logs. Unique subdomains aggregates all certificates into one row per discovered hostname (with first seen, last seen and certificate count).

## `includeSubdomains` (type: `boolean`):

When on (recommended), discover every subdomain of the domain. When off, only certificates that exactly match the domain itself are returned.

## `maxResults` (type: `integer`):

Maximum number of records to collect across all domains. Free Apify accounts are capped at 10 per run.

## `excludeExpired` (type: `boolean`):

Skip certificates whose validity period has already ended.

## `currentlyValidOnly` (type: `boolean`):

Only return certificates that are valid right now (not expired and not yet-to-start).

## `wildcardOnly` (type: `boolean`):

Only return wildcard certificates (those covering \*.domain).

## `issuer` (type: `string`):

Only return certificates whose issuer contains this text, for example Let's Encrypt, DigiCert, Sectigo, Google.

## `matchHostname` (type: `string`):

Only return certificates that include a hostname containing this text, for example api, vpn, staging, mail.

## `sinceDate` (type: `string`):

Only return certificates that became valid on or after this date (YYYY-MM-DD). Useful for monitoring newly issued certificates.

## `withLiveResolve` (type: `boolean`):

Optional paid add-on (default off). For each discovered hostname, perform a live DNS-over-HTTPS lookup to check whether it still resolves today, returning isLive, current A/AAAA IPs and any CNAME. Turns a historical certificate list into a live attack-surface map. Billed only per hostname that is actually resolved, and disabled for free users.

## `withAiRisk` (type: `boolean`):

Optional paid AI add-on (default off). Uses AI to produce a concise 2-3 sentence attack-surface exposure assessment per domain, flagging risky subdomains (dev, staging, vpn, admin, internal), wildcard usage and issuer diversity. Billed once per domain, only when a usable summary is produced, and disabled for free users.

## `proxyConfiguration` (type: `object`):

Proxy settings. Residential proxy is recommended for the most reliable results.

## Actor input object example

```json
{
  "domain": "github.com",
  "outputMode": "Certificates",
  "includeSubdomains": true,
  "maxResults": 50,
  "excludeExpired": false,
  "currentlyValidOnly": false,
  "wildcardOnly": false,
  "withLiveResolve": false,
  "withAiRisk": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "domain": "github.com",
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapers_lat/certificate-transparency-scraper").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 = {
    "domain": "github.com",
    "maxResults": 50,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapers_lat/certificate-transparency-scraper").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 '{
  "domain": "github.com",
  "maxResults": 50,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call scrapers_lat/certificate-transparency-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapers_lat/certificate-transparency-scraper"
        }
    }
}

```

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/rnIIvWtKji5L8rBfu/builds/hzvdXdKJFdDGotPvr/openapi.json
