# SSL Certificate Subdomain Finder: CT Log Search (`transparent_meteorite/ssl-certificate-subdomain-finder`) Actor

List the subdomains of any domain from public Certificate Transparency logs. Returns each hostname with first seen, last seen, expiry, issuer, certificate count and a freshness score. No login, no proxy.

- **URL**: https://apify.com/transparent_meteorite/ssl-certificate-subdomain-finder.md
- **Developed by:** [Detroit Web Agent - Open Data](https://apify.com/transparent_meteorite) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.47 / 1,000 hostnames

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Subdomain Finder: List Subdomains from Certificate Transparency Logs

**Subdomain finder** that reads public SSL Certificate Transparency logs: one row per hostname for any domain you list, with first seen, last seen, expiry status, issuers, certificate count and a freshness score, without ever contacting the domains you look up.

**This Actor vs onescales/real-subdomain-finder:** that one is the most-used subdomain finder and queries 40+ OSINT sources with DNS validation, so it can find more hosts. This one reads only public certificate logs and never contacts the target, and adds expiry status, a freshness score and a first-seen-within-N-days filter for spotting new hosts.

Find the subdomains of any domain by reading the public Certificate Transparency (CT) logs. Every time a certificate authority issues an SSL/TLS certificate, the hostnames on it are written to public logs. This actor searches those logs for the domains you list and returns one row per hostname, with the date it first appeared, when its newest certificate expires, who issued it, and how many certificates it has had.

It reads only public records. It never contacts the domains you look up, so there is nothing to scan, no login, and no proxy.

### What does this Actor do?

For each domain you enter, the actor asks the public crt.sh search for every certificate that names that domain or any subdomain of it. If crt.sh does not answer, it falls back to the Cert Spotter public API. It then merges all certificates into one record per hostname and adds a few computed fields:

- `firstSeenAt`: the issue date of the oldest certificate that names the host.
- `lastSeenAt`: the issue date of the newest one.
- `expiresAt` and `status`: `active`, `expiring_soon` (30 days or less) or `expired`.
- `newScore`: a 0 to 100 freshness score. Recently appearing hostnames score high.
- `certCount`, `issuers`, `depth`, and a link to the newest certificate on crt.sh.

**Run in 30 seconds**

1. Open the Actor and press **Try for free** (a free Apify account is enough).
2. Keep the two prefilled domains and press **Start**. A run takes about a minute.
3. Open the **Output** tab. Use the table view or download CSV, Excel or JSON.

### Input

| Field | What it does |
|---|---|
| `domains` | List of domains, for example `example.com`. A full URL also works. |
| `hostnameContains` | Keep hostnames containing one of these words, for example `staging`, `dev`, `vpn`. |
| `newWithinDays` | Keep hostnames first seen in the last N days. 0 means no limit. |
| `statusFilter` | `all` (default), `active`, or `expiring_soon`. |
| `includeExpired` | Turn off to read only certificates that are still valid. |
| `maxItems` | Stop after this many hostnames. |

Sample input:

```json
{
  "domains": ["apify.com", "anthropic.com"],
  "hostnameContains": ["api", "dev", "staging"],
  "newWithinDays": 90,
  "maxItems": 100
}
```

### Output

One row per hostname:

| Field | Meaning |
|---|---|
| `subdomain`, `rootDomain` | The hostname and the domain you searched. |
| `depth` | Number of labels in front of the root domain. 0 is the root itself. |
| `status` | `active`, `expiring_soon`, `expired` or `unknown`. |
| `newScore` | Freshness score from 0 to 100. |
| `firstSeenAt`, `lastSeenAt` | ISO dates of the oldest and newest certificate issue. |
| `expiresAt`, `daysToExpiry` | Newest expiry date and days left (negative if expired). |
| `daysSinceFirstSeen` | Whole days since the first certificate. |
| `certCount`, `issuers` | How many certificates name the host, and which authorities issued them. |
| `coveredByWildcard` | True if a wildcard certificate such as `*.example.com` also covers it. |
| `certUrl`, `sourceUrl`, `latestCertId` | Links to evidence on crt.sh. |
| `source`, `checkedAt` | Which service answered, and when. |

### Sample output

```json
{
  "subdomain": "staging.example.com",
  "rootDomain": "example.com",
  "depth": 1,
  "status": "active",
  "newScore": 79,
  "firstSeenAt": "2026-10-12T08:14:03.000Z",
  "lastSeenAt": "2026-10-12T08:14:03.000Z",
  "expiresAt": "2027-01-10T08:14:02.000Z",
  "daysSinceFirstSeen": 9,
  "certCount": 1,
  "issuers": ["Let's Encrypt"],
  "certUrl": "https://crt.sh/?id=123456789",
  "source": "crt.sh"
}
```

### Use cases

- Map the public footprint of your own company and spot forgotten hosts such as old staging or test sites before an attacker does.
- Run it weekly with `newWithinDays` set to 7 and send new hostnames to Slack, a ticket queue or an n8n workflow.
- Prepare a pen test or bug bounty scope from public data, with the evidence link on every row.
- Watch a competitor or an acquisition target for new product subdomains.
- Check certificate expiry across a list of domains with `statusFilter` set to `expiring_soon`.

### Why use it

- **Public data only.** CT logs are open by design. No login, no cookies, no proxy.
- **Nothing touches the target.** The actor never connects to the domains you look up.
- **Evidence on every row.** Each hostname links to its certificate on crt.sh.
- **Backup source.** If crt.sh is busy, the run falls back to Cert Spotter instead of failing.

### Pricing

Pay per event. You pay a small fixed amount per hostname delivered, listed on the Pricing tab, plus a tiny start fee per run. Hostnames removed by your filters are never charged, and you can set a maximum cost per run in the run options.

### FAQ

**Does this find every subdomain?**
No. It finds hostnames that appeared on a publicly logged certificate. A host that only uses plain HTTP, a private certificate authority, or a wildcard certificate will not show up by name.

**Why is a hostname listed that no longer exists?**
Certificates stay in the logs forever. Use `status` and `daysToExpiry` to tell old records from live ones. A valid certificate does not prove the host still answers.

**Is this a scanner?**
No. It only reads public records. It sends no traffic to the domains you enter.

**Why does a large domain take longer?**
Big companies have tens of thousands of certificates. crt.sh can take up to a minute for them. Use `newWithinDays` or `hostnameContains` to narrow the output.

### Limits

- The data is only as complete as the public CT logs and the crt.sh index.
- crt.sh is a free shared service and can be slow or return errors. The actor retries and then falls back to Cert Spotter, whose free quota is small.
- One domain is read at a time to stay polite to the service.
- This is not security advice. Confirm findings before acting on them.

### Related Actors

- [Domain Intelligence Lookup](https://apify.com/transparent_meteorite/domain-intelligence-lookup) adds registration and DNS details for a domain.
- [Technical SEO Page Audit](https://apify.com/transparent_meteorite/technical-seo-page-audit) audits the pages on a site.
- [Sitemap Link Inventory](https://apify.com/transparent_meteorite/sitemap-link-inventory) lists the URLs a site publishes in its sitemap.

Found a bug or need a field? Open an issue on the Issues tab with the run URL.

### More from DWA Open Data

Browse all 69 data Actors, with live prices and sample output, at [open-data-actors.pages.dev](https://open-data-actors.pages.dev).

***

**Feedback:** if this Actor was useful, or if it fell short, an honest review on the [Reviews tab](https://apify.com/transparent_meteorite/ssl-certificate-subdomain-finder/reviews) helps other users decide. Problems or feature requests: please open an [Issue](https://apify.com/transparent_meteorite/ssl-certificate-subdomain-finder/issues) and we usually reply within one business day.

# Actor input Schema

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

Domains to look up, for example example.com. Subdomains of each domain are found from public certificate logs. A full URL also works. Leave empty to use the two example domains.

## `hostnameContains` (type: `array`):

Keep hostnames that contain at least one of these words (case-insensitive). Example: \["staging", "dev", "admin", "vpn"]. Leave empty for all hostnames.

## `newWithinDays` (type: `integer`):

Keep only hostnames whose first certificate was issued in the last N days. Good for spotting new services. 0 = no limit.

## `statusFilter` (type: `string`):

active keeps hostnames whose newest certificate has not expired. expiring_soon keeps those that expire within 30 days.

## `includeExpired` (type: `boolean`):

Turn off to read only certificates that are still valid. Hostnames that only ever had expired certificates are then missing.

## `maxItems` (type: `integer`):

Stop after this many hostnames. You pay only for hostnames delivered.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "anthropic.com"
  ],
  "newWithinDays": 0,
  "statusFilter": "all",
  "includeExpired": true,
  "maxItems": 100
}
```

# Actor output Schema

## `overview` (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": [
        "apify.com",
        "anthropic.com"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("transparent_meteorite/ssl-certificate-subdomain-finder").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": [
        "apify.com",
        "anthropic.com",
    ],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("transparent_meteorite/ssl-certificate-subdomain-finder").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": [
    "apify.com",
    "anthropic.com"
  ],
  "maxItems": 100
}' |
apify call transparent_meteorite/ssl-certificate-subdomain-finder --silent --output-dataset

```

## MCP server setup

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

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/zjpYskSLTSduTpcLL/builds/GFn2HxpWPVh801b4g/openapi.json
