# Subdomain Finder & Recon Tool (`andok/subdomain-finder`) Actor

Discover subdomains for any target via passive OSINT sources. Ideal for security bug bounties and attack surface mapping.

- **URL**: https://apify.com/andok/subdomain-finder.md
- **Developed by:** [Andok](https://apify.com/andok) (community)
- **Categories:** Business, Developer tools
- **Features:** Limited permissions
- **Stats:** 37 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.47 / 1,000 domain scans

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

## Subdomain Finder (CT Logs + DNS)

Map the full attack surface of any domain by discovering subdomains through certificate transparency logs and optional DNS brute-force. Security audits and penetration tests start with knowing what is exposed — yet manual subdomain enumeration is slow and incomplete. Scan multiple domains in bulk with configurable concurrency and get structured results ready for downstream security tools.

### Features

- **Certificate transparency** — queries crt.sh to find subdomains from publicly issued TLS certificates
- **DNS brute-force** — optional wordlist-based subdomain discovery for common names like api, staging, admin
- **Bulk scanning** — process multiple root domains in a single run
- **Configurable concurrency** — control parallel lookups from 1 to 25 simultaneous queries
- **Source tracking** — reports how many subdomains came from each discovery method
- **Custom wordlists** — extend or replace the default brute-force wordlist with your own terms
- **Charge limit support** — respects the Apify max charge per run to control costs

### Input

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `domains` | `array` | No | `["example.com"]` | Root domains to scan for subdomains |
| `domain` | `string` | No | — | Single domain to scan (backwards compatible, use `domains` for bulk) |
| `useCertificateTransparency` | `boolean` | No | `true` | Query certificate transparency logs (crt.sh) for subdomain discovery |
| `useDnsBruteforce` | `boolean` | No | `false` | Check a wordlist of common subdomain names via DNS resolution |
| `bruteforceWords` | `array` | No | `["www", "mail", "api", ...]` | Custom wordlist for DNS brute-force. Only used when brute-force is enabled |
| `timeoutSeconds` | `integer` | No | `15` | Timeout in seconds for each DNS or HTTP request |
| `concurrency` | `integer` | No | `5` | Number of parallel domain lookups (1-25) |

#### Input Example

```json
{
  "domains": ["example.com", "example.org"],
  "useCertificateTransparency": true,
  "useDnsBruteforce": true,
  "concurrency": 10
}
```

### Output

Each root domain produces one dataset item with all discovered subdomains and source counts.

Key fields:

- `domain` (`string`) — the root domain that was scanned
- `subdomainCount` (`integer`) — total number of unique subdomains found
- `subdomains` (`array`) — sorted list of all discovered subdomains
- `sources` (`object`) — count of subdomains found per method (crtsh, dnsBruteforce)
- `checkedAt` (`string`) — ISO 8601 timestamp of the scan
- `error` (`string | null`) — any issues encountered during the scan

#### Output Example

```json
{
  "domain": "example.com",
  "subdomainCount": 12,
  "subdomains": [
    "api.example.com",
    "blog.example.com",
    "cdn.example.com",
    "dev.example.com",
    "mail.example.com",
    "staging.example.com",
    "status.example.com",
    "support.example.com",
    "vpn.example.com",
    "wiki.example.com",
    "www.example.com",
    "zabbix.example.com"
  ],
  "sources": {
    "crtsh": 10,
    "dnsBruteforce": 4
  },
  "checkedAt": "2025-03-09T14:30:00.000Z",
  "error": null
}
```

### Pricing

| Event | Cost |
|-------|------|
| Domain Scan | Pay-per-event pricing applies |

Set `ACTOR_MAX_TOTAL_CHARGE_USD` to control maximum spending per run.

### Use Cases

- **Penetration testing reconnaissance** — discover all exposed subdomains before beginning a security assessment
- **Attack surface management** — schedule weekly scans to detect new or unauthorized subdomains as they appear
- **Brand protection** — find subdomains that may have been forgotten, misconfigured, or hijacked
- **Certificate audit preparation** — enumerate subdomains to feed into SSL certificate monitoring
- **Infrastructure inventory** — build a complete map of subdomains across multiple client domains for MSPs and agencies

### Related Actors

| Actor | What it adds |
|-------|-------------|
| [DNS Propagation Checker](https://apify.com/andok/dns-propagation-checker) | Verify DNS records for discovered subdomains across global resolvers |
| [SSL Certificate Monitor](https://apify.com/andok/ssl-certificate-monitor) | Check SSL certificate health for every subdomain found |
| [Security Headers Analyzer](https://apify.com/andok/security-headers-analyzer) | Audit HTTP security headers on discovered subdomains |

### Notes

- Certificate transparency results depend on crt.sh availability. If crt.sh is temporarily down, the actor logs the error and continues with DNS brute-force if enabled.
- DNS brute-force only checks the provided wordlist — it does not perform exhaustive enumeration. Extend `bruteforceWords` for deeper coverage.

# Actor input Schema

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

Root domains to scan for subdomains (e.g. example.com). Each domain is checked against certificate transparency logs and optionally brute-forced via DNS.

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

Single domain to scan. Use the 'Domains' field above for bulk scanning — this field exists for backwards compatibility.

## `useCertificateTransparency` (type: `boolean`):

Query crt.sh certificate transparency logs to discover subdomains that appear in publicly issued TLS certificates.

## `useDnsBruteforce` (type: `boolean`):

Check a wordlist of common subdomain names (www, api, mail, staging, etc.) by resolving DNS. Enable alongside CT for broader coverage.

## `bruteforceWords` (type: `array`):

Custom wordlist for DNS brute-force discovery. Only used when DNS bruteforce is enabled. The default list covers common names like www, api, mail, staging, and admin.

## `timeoutSeconds` (type: `integer`):

Maximum time in seconds to wait for each DNS or crt.sh request to respond.

## `concurrency` (type: `integer`):

Number of domains to process in parallel. Higher values speed up bulk scans but increase memory usage.

## Actor input object example

```json
{
  "domains": [
    "example.com"
  ],
  "useCertificateTransparency": true,
  "useDnsBruteforce": false,
  "bruteforceWords": [
    "www",
    "mail",
    "api",
    "dev",
    "staging",
    "test",
    "blog",
    "app",
    "portal",
    "admin",
    "cdn",
    "static",
    "m",
    "beta"
  ],
  "timeoutSeconds": 15,
  "concurrency": 5
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

## `run` (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"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("andok/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": ["example.com"] }

# Run the Actor and wait for it to finish
run = client.actor("andok/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": [
    "example.com"
  ]
}' |
apify call andok/subdomain-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,andok/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/nKxhTgaytEUJQbue1/builds/dUAXdrLnPJQCx4pea/openapi.json
