# Subdomain Finder: Certificate Transparency Logs | $1/1K (`one_dollar_store/subdomain-finder-crtsh`) Actor

$1 per 1,000 results, platform usage included. Subdomains of any domain found in public certificate transparency logs (crt.sh, with a back up source): first and last seen, certificate count, issuer and expiry. Passive, no scanning. No API key.

- **URL**: https://apify.com/one_dollar_store/subdomain-finder-crtsh.md
- **Developed by:** [One Dollar Store](https://apify.com/one_dollar_store) (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 $1.00 / 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.

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

## Subdomain Finder: Subdomains from Certificate Transparency Logs for Any Domain

**$1 per 1,000 subdomains. Platform usage included. No rental, no minimum.**

Give it a domain and it lists the subdomains that have appeared in public certificate transparency logs, read through crt.sh. Each subdomain comes with the dates it was first and last seen on a certificate, how many certificates named it, the issuer and when the newest one expires. It is passive: nothing is scanned and your target is never contacted. No account and no API key.

[Open it in Apify Console](https://console.apify.com/actors/pvt8OKTaK0pMfLqSC/input)

### What it costs

| Subdomains | This actor |
|---|---|
| 1,000 | $1.00 |
| 10,000 | $10.00 |
| 100,000 | $100.00 |

Plus $0.001 per run. One flat price, platform usage included, so there is no separate compute or proxy bill. Only subdomain rows are charged. A domain that has no certificates in the logs, or a search that fails, returns no row and costs nothing beyond the run fee. A weekly check of 20 domains that finds 2,000 subdomains costs about $2.00 a run.

### Why use it

- **One flat price.** The bill follows the number of subdomains and nothing else.
- **Built for a slow source.** crt.sh is free but often slow or busy. The actor reads its answer as a stream, caps every attempt in time and size, retries up to twice (asking for valid certificates only when the full query is too heavy), and falls back to a second public source. A run does not hang.
- **History, not only today.** Old names that no longer resolve are kept, with first and last seen dates, unless you ask for valid certificates only.
- **Clean rows.** Certificates are counted once even when a log lists both the precertificate and the final one. Email addresses and names outside your domain are dropped.

### Quick start

1. Open the actor, type a domain, press **Start**.
2. Or paste this input:

```json
{ "domains": ["python.org"], "onlyValidNow": false, "maxSubdomainsPerDomain": 200 }
```

3. Download the results as JSON, CSV or Excel, or read them through the API.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/one_dollar_store~subdomain-finder-crtsh/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["python.org"], "maxSubdomainsPerDomain": 100}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("one_dollar_store/subdomain-finder-crtsh").call(
    run_input={"domains": ["python.org"], "maxSubdomainsPerDomain": 100}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["subdomain"], item["lastSeen"], item["currentlyValid"])
```

### Use it from an AI assistant

Claude, ChatGPT, Cursor and other assistants can call this actor through Apify's MCP server. Add it with this server address:

```
https://mcp.apify.com?tools=one_dollar_store/subdomain-finder-crtsh
```

Then ask, for example: "List the subdomains of python.org that have a valid certificate today and tell me which ones were first seen this year."

### Switching from another subdomain finder

Domains go in `domains` (a list, so one run can cover many). Limits are `maxSubdomainsPerDomain` and `maxItems`. The core output fields are `subdomain`, `domain`, `firstSeen`, `lastSeen` and `currentlyValid`. The actor does not resolve names or probe hosts, so there is no IP address field. Use the DNS Records Lookup from the same store for that.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `domains` | list of text | required | Domains to search, for example `python.org`. A subdomain such as `docs.python.org` finds the names below it. |
| `onlyValidNow` | true or false | false | Keep only names whose newest certificate has not expired. Also a lighter search for big domains. |
| `includeWildcards` | true or false | false | Adds names such as `*.python.org` as their own rows, marked `isWildcard`. |
| `maxSubdomainsPerDomain` | number | 1000 | Most subdomains per domain, in alphabetical order. |
| `maxItems` | number | 1000 | Most rows in the whole run. Minimum 10. |

### Output fields

| Field | Meaning |
|---|---|
| `subdomain` | The host name, in lower case. |
| `domain` | The domain you searched. |
| `firstSeen`, `lastSeen` | Start date of the oldest and of the newest certificate that names it (UTC). |
| `validUntil`, `currentlyValid` | Expiry of the latest certificate and whether it is still valid today. |
| `certificates` | How many different certificates name it. |
| `issuer` | Certificate authority of the newest certificate. |
| `isWildcard` | `true` for a wildcard name. Only present with `includeWildcards`. |
| `latestCertificateUrl` | The crt.sh page of the newest certificate. Only for crt.sh results. |
| `source` | `crt.sh`, `crt.sh (valid certificates only)` or `certspotter`. |

Empty fields are left out of a row. The apex name itself (`python.org`) is not a subdomain and is not returned.

### Sample results

Real rows from a test run on 9 October 2026 for `python.org`.

```json
[
  {"domain": "python.org", "subdomain": "blog.python.org", "firstSeen": "2026-02-27T21:59:35.000Z", "lastSeen": "2026-08-27T08:12:49.000Z", "validUntil": "2026-11-25T08:12:48.000Z", "currentlyValid": true, "certificates": 4, "issuer": "Let's Encrypt", "latestCertificateUrl": "https://crt.sh/?id=29417390764", "source": "crt.sh"},
  {"domain": "python.org", "subdomain": "docs.python.org", "firstSeen": "2014-09-05T00:00:00.000Z", "lastSeen": "2023-06-29T16:48:43.000Z", "validUntil": "2024-07-30T16:48:42.000Z", "currentlyValid": false, "certificates": 26, "issuer": "GlobalSign nv-sa", "latestCertificateUrl": "https://crt.sh/?id=9781430053", "source": "crt.sh"},
  {"domain": "python.org", "subdomain": "mail.python.org", "firstSeen": "2011-10-10T00:00:00.000Z", "lastSeen": "2026-07-14T06:05:58.000Z", "validUntil": "2026-10-12T06:05:57.000Z", "currentlyValid": true, "certificates": 83, "issuer": "Let's Encrypt", "latestCertificateUrl": "https://crt.sh/?id=27919353165", "source": "crt.sh"},
  {"domain": "python.org", "subdomain": "packaging.python.org", "firstSeen": "2014-09-05T00:00:00.000Z", "lastSeen": "2026-09-26T09:59:26.000Z", "validUntil": "2026-12-25T09:59:25.000Z", "currentlyValid": true, "certificates": 61, "issuer": "Let's Encrypt", "latestCertificateUrl": "https://crt.sh/?id=29619280969", "source": "crt.sh"}
]
```

### Limits

- **crt.sh decides how fast and how complete this is.** It is free and often slow. The actor tries crt.sh up to three times, each try capped at 70, 50 and 40 seconds, and the last try asks for valid certificates only (`source` says so). Very large domains often fail on crt.sh; a stream that is cut by the time cap or by a size cap of about 120 MB still returns the rows read so far, and the run summary marks the domain `truncated`.
- **Back up source.** If crt.sh gives nothing, the actor asks Certspotter without a key. It lists mostly current certificates and stops after about 4,000 of them, so `firstSeen` and `certificates` are thinner and a huge domain is incomplete. `source` says `certspotter`. If both sources fail, the domain returns no row and is listed under `failedDomains`.
- **Logs show certificate names, not live hosts.** A name can be in a log and no longer exist, and a host can exist without ever having had a public certificate. Use `currentlyValid` and `lastSeen` as hints, and check with a DNS lookup.
- **Wildcards hide names.** A certificate for `*.example.com` covers every subdomain without listing them. Internal names behind a wildcard will not show up.
- **Some names never reach public logs.** Certificates from private authorities are not logged.
- **Alphabetical cut.** When `maxSubdomainsPerDomain` is lower than the number found, the first names in alphabetical order are returned.

### FAQ

**How much does it cost to list 10,000 subdomains?**
$10, plus $0.001 for each run.

**Do I pay for compute or proxy on top?**
No. Platform usage is included in the $1 per 1,000 price.

**Does it touch the target domain?**
No. It reads public certificate transparency logs through crt.sh. Nothing is sent to the domain you search.

**Why did a run take a minute or more?**
crt.sh builds each answer on demand and can be slow for big domains. The actor waits for it, up to the caps above, and then tries again or falls back.

**Why is there no IP address?**
The actor does not resolve names. Feed the list to the DNS Records Lookup if you need A and AAAA records.

**Is it legal?**
Certificate transparency logs are public by design, and the actor only reads them. How you use the results is up to you: follow the terms of crt.sh and Certspotter, and the law where you live. Finding names in logs is not permission to test a system you do not own.

**Is this an official crt.sh, Sectigo or Certspotter product?**
No. It is an independent tool and is not affiliated with or endorsed by any of them.

**Do I need an Apify account?**
Yes. Actors run from an Apify account, and a free account is enough to start: it includes $5 of platform usage every month. You can [sign up here](https://www.apify.com?fpr=ymnoit). This is a referral link and it costs you nothing.

**Is there a limit on the free plan?**
Yes. A run started from a free plan account delivers the first 10 results, then ends with a message and a link to the plans. Any paid plan returns everything you ask for, up to your own limit. The price per result is the same on every plan.

### More from The One Dollar Store

Every actor here costs $1 per 1,000 results, platform usage included. See the whole store: https://apify.com/one_dollar_store

**Domains and apps**

- [Apple App Store Scraper](https://apify.com/one_dollar_store/app-store-apps-scraper): App details, ratings and search results.
- [DNS Records Lookup](https://apify.com/one_dollar_store/dns-records-lookup): DNS records for any list of domains.
- [Domain WHOIS Lookup](https://apify.com/one_dollar_store/domain-whois-rdap-lookup): Registrar, dates and name servers for any domain.
- [Shopify App Store Scraper](https://apify.com/one_dollar_store/shopify-app-store-scraper): Shopify apps with ratings and pricing.
- [Hugging Face Scraper](https://apify.com/one_dollar_store/hugging-face-models-scraper): Models and datasets with downloads and tags.

### Changelog

- October 2026: first release.

# Actor input Schema

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

Domains to search, one per line, for example example.com. A subdomain such as dev.example.com is allowed and finds the names below it. Links are reduced to the host name.

## `onlyValidNow` (type: `boolean`):

Off: every name that ever appeared in a certificate, including old ones. On: only names whose newest certificate has not expired yet. This also makes the search lighter for big domains.

## `includeWildcards` (type: `boolean`):

Adds names such as \*.example.com as their own rows, marked isWildcard. Off by default because they are not real host names.

## `maxSubdomainsPerDomain` (type: `integer`):

The most subdomains to return for each domain, in alphabetical order.

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

The run stops after this many rows in total. Minimum 10.

## Actor input object example

```json
{
  "domains": [
    "python.org"
  ],
  "onlyValidNow": false,
  "includeWildcards": false,
  "maxSubdomainsPerDomain": 200,
  "maxItems": 200
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "python.org"
    ],
    "onlyValidNow": false,
    "includeWildcards": false,
    "maxSubdomainsPerDomain": 200,
    "maxItems": 200
};

// Run the Actor and wait for it to finish
const run = await client.actor("one_dollar_store/subdomain-finder-crtsh").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": ["python.org"],
    "onlyValidNow": False,
    "includeWildcards": False,
    "maxSubdomainsPerDomain": 200,
    "maxItems": 200,
}

# Run the Actor and wait for it to finish
run = client.actor("one_dollar_store/subdomain-finder-crtsh").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": [
    "python.org"
  ],
  "onlyValidNow": false,
  "includeWildcards": false,
  "maxSubdomainsPerDomain": 200,
  "maxItems": 200
}' |
apify call one_dollar_store/subdomain-finder-crtsh --silent --output-dataset

```

## MCP server setup

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

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/pvt8OKTaK0pMfLqSC/builds/jezMRFxB7ROQLBpuV/openapi.json
