Subdomain Finder API — Certificate Logs & DNS, No Key avatar

Subdomain Finder API — Certificate Logs & DNS, No Key

Pricing

from $0.30 / 1,000 subdomains

Go to Apify Store
Subdomain Finder API — Certificate Logs & DNS, No Key

Subdomain Finder API — Certificate Logs & DNS, No Key

Find a domain's subdomains in public certificate-transparency logs (crt.sh and Cert Spotter), resolve each over DNS-over-HTTPS (A, AAAA, CNAME) and optionally check which answer on the web: status, title, server. Hostnames only. No API key, no login.

Pricing

from $0.30 / 1,000 subdomains

Rating

0.0

(0)

Developer

Insight Solutions

Insight Solutions

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Every subdomain a company has ever had a certificate for, checked against DNS today. Give this Actor a domain — apify.com, www.basecamp.com, or a full URL — and it reads the public Certificate Transparency logs through two independent services (crt.sh and Cert Spotter), merges what they know, resolves every name over DNS-over-HTTPS, and, if you ask, checks which ones answer on the web. One row per hostname: where it was found, how many certificates named it and when, its A/AAAA/CNAME records, and its HTTP status, title and server.

No API key. No login. No wordlist guessing. Hostnames only — there is no personal data in this Actor's output at all. $0.50 per 1,000 subdomains, DNS included; a run that finds nothing costs nothing.

Try it in 30 seconds

{
"domains": ["apify.com"],
"sources": ["crtsh", "certspotter"],
"resolveDns": true,
"checkHttp": false
}

That block is the Store prefill — paste it and run. For apify.com the 2026-10-07 captures hold 36 subdomains, 14 of which have had no valid certificate for months or years. Most of the run is crt.sh thinking: it took 11–16 seconds per domain in our captures.

Want to know which hosts are actually up? Add "checkHttp": true (and "onlyResolving": true to drop the names that no longer exist).

Price — $0.50 per 1,000 subdomains on the FREE tier (+ $0.001 per run), DNS resolution included; the optional HTTP check is $0.30 per 1,000 hosts checked. Summary rows, diagnostic rows and names you filter out are free. Pay-per-event, limited permissions — works over the Apify MCP server (mcp.apify.com) and with agentic (x402) payments.

From code — client.actor("insight.solutions/subdomain-finder-api").call(run_input={…}) with apify-client, or POST https://api.apify.com/v2/acts/insight.solutions~subdomain-finder-api/run-sync-get-dataset-items.

What comes back

One subdomain row per hostname — this one built from the 2026-10-07 apify.com captures:

{
"ok": true,
"rowType": "subdomain", // "subdomain" | "domain" (summary) | "diagnostic"
"input": "apify.com",
"domain": "apify.com", // the apex that was searched
"hostname": "odoo.apify.com",
"isApex": false,
"isWildcard": false, // true when *.odoo.apify.com is on a certificate
"depth": 1, // labels below the apex
// --- certificate evidence ---
"sources": ["crtsh", "certspotter"], // which sources listed it
"certCount": 6, // distinct certificates naming it
"firstSeen": "2025-12-07T14:41:19.000Z", // earliest not_before
"lastSeen": "2027-01-01T10:08:22.000Z", // latest not_after
"issuers": ["Let's Encrypt"], // most recently used first, ≤ 5
// --- DNS, today ---
"dnsStatus": "ok", // ok | nxdomain | servfail | timeout | error
"a": ["34.52.252.219"],
"aaaa": [],
"cname": null,
"resolves": true,
// --- HTTP check (null unless checkHttp is on) ---
"httpStatus": null,
"httpFinalUrl": null,
"httpTitle": null,
"httpServer": null,
"httpMs": null,
"httpScheme": null,
"httpError": null,
"error": null,
"errorType": null,
"scrapedAt": "2026-10-07T21:04:40.000Z",
"source": "crtsh+certspotter",
"sourceUrl": "https://crt.sh/?q=%25.apify.com&output=json"
}

Read sdk.apify.com from the same run next to it: "sources": ["crtsh"], "certCount": 27, "lastSeen": "2023-04-25T06:30:50.000Z" — a host that had certificates for five years and none since 2023. The certificate history and today's DNS answer, side by side, are the point: a name that is in the logs but gives nxdomain is retired infrastructure; a name that resolves but has no current certificate is worth a second look.

After each domain's last subdomain row comes one free domain summary row:

{
"ok": true,
"rowType": "domain",
"domain": "apify.com",
"subdomainCount": 36,
"resolvingCount": 18,
"liveCount": 0, // HTTP check was off
"wildcardCount": 4,
"certificateCount": 529, // distinct certificates under apify.com
"sourceCounts": { "crtsh": 36, "certspotter": 20, "hackertarget": null },
"sourceStatus": { "crtsh": "ok", "certspotter": "ok", "hackertarget": null },
"sourceMs": { "crtsh": 15927, "certspotter": 659, "hackertarget": null },
"droppedOutsideApex": 36, // other companies' names on shared certificates
"droppedInvalid": 0,
"filteredCount": 0,
"undeliveredCount": 0,
"truncated": false,
"diagnosticTypes": []
}

Anything that could not be read is a free diagnostic row (ok: false) with an errorType and a sentence in error:

errorTypeWhen
source-unavailablecrt.sh (or Cert Spotter, or HackerTarget) did not answer after its retries. The other sources' names are still delivered.
source-rate-limitedCert Spotter answered 429 (its anonymous quota), HackerTarget's daily quota is spent, or crt.sh answered 429 three times.
invalid-inputThe entry is not a domain: an IP address, a bare public suffix such as co.uk, a hostname without a TLD.
timeoutThe run's time budget ran out before a domain was searched, or with some of its names not yet resolved.
no-resultsThe sources answered but listed no name under the domain, or onlyResolving left nothing.

Use cases

  • Attack-surface inventory. Find the staging hosts, forgotten admin panels and regional sites a company has put certificates on, and see which still resolve.
  • Dangling DNS. A row with cname set and resolves: false is a CNAME whose target no longer exists — the classic subdomain-takeover pattern. Check it before someone else does.
  • SEO and migrations. Every hostname that ever served HTTPS — old blog domains, www variants, regional sites — so redirects and canonicals can be audited.
  • Sales and market intelligence. Subdomains name the tools a company runs (status., trust., odoo., discord.): a cheap signal of their stack and their SaaS vendors.
  • Monitoring your own domains. Schedule it weekly and diff the output: a new name in the logs is a new certificate somebody requested.

How it works

  1. Read the domain. Scheme, path, port and www. are dropped and the registrable domain is kept: docs.example.co.uk searches example.co.uk; under a public suffix such as github.io the user's own site (octocat.github.io) is the domain. One domain sent three ways is searched once.
  2. Ask the certificate sources, in parallel. crt.sh (https://crt.sh/?q=%25.<domain>&output=json) has the deep history. Cert Spotter (api.certspotter.com/v1/issuances) has the newest certificates — every one it listed in our capture was still valid; pages are followed with after=<last id> while a page comes back full (100), up to ten pages. HackerTarget's host search, if you turned it on, is asked after them.
  3. Merge. Names are lower-cased, trailing dots removed, and anything that is not a hostname — an email identity from an S/MIME certificate, an IP, a name with a space — is dropped and counted, never shown. Names that belong to other domains (shared certificates list dozens of companies) are dropped and counted. crt.sh lists every certificate twice (precertificate and final certificate); those are folded, and a certificate both sources saw is counted once — matched on its validity window and the names it covers, because the two services expose no common identifier. Wildcards are folded into their parent (*.staging.apify.com → staging.apify.com, isWildcard: true) unless you keep them. The list is sorted — the apex first, then alphabetical — and capped at maxSubdomainsPerDomain.
  4. Resolve. Each name gets an A lookup and, if it exists, an AAAA lookup, over DNS-over-HTTPS: Cloudflare first, Google if Cloudflare does not give a DNS answer. NXDOMAIN is an answer and is not asked twice. A CNAME is read from the resolver's answer chain, including on NXDOMAIN, which is how a dangling CNAME shows up.
  5. Check (optional). One GET to https://<host>/, and one to http://<host>/ only if https got no answer. Any HTTP status counts as an answer. The first 64 KB of an HTML body is read for its <title>; redirects are followed (up to ten) and the final URL kept. Never HEAD. Hosts with no address are not checked.
  6. Deliver. Rows are pushed in list order, in batches of 25 as they finish, charged only after they are in your dataset, and each domain ends with its summary row.

Why it keeps working when crt.sh does not. crt.sh is a free public service and is often overloaded: it is given 60 seconds, then retried after 5 seconds and again after 15. If it still will not answer you get a free source-unavailable row and Cert Spotter's names — resolved, delivered and billed as usual. The retries are cut short when they would eat into the last 30 seconds of the run (or the last quarter of a short run), so there is always time left to resolve what the other source found.

Being a good citizen. At most two domains are searched at once, so crt.sh never sees more than two queries from a run. A Cert Spotter 429 is reported, not dodged from another IP. A refused exit IP (HTTP 403) is retried once from a fresh proxy session, then reported. Pages of one source are spaced 250–600 ms apart.

Input reference

FieldTypeDefaultWhat it does
domainsarray of strings— (required)Domains, hosts or URLs. Reduced to the registrable domain and de-duplicated.
sourcesarray["crtsh", "certspotter"]Any of crtsh, certspotter, hackertarget (opt-in).
includeWildcardsbooleanfalseKeep *.x names as rows of their own instead of folding them into x. Wildcard rows are never resolved or HTTP-checked.
resolveDnsbooleantrueA/AAAA (and CNAME from the answer) over DNS-over-HTTPS. Included in the row price.
onlyResolvingbooleanfalseLeave out names with no A/AAAA address. Left-out names are free. Turns resolveDns on.
checkHttpbooleanfalseThe HTTP live check. Billed per host requested.
includeExpiredbooleantrueLet expired certificates count as evidence. Off keeps only names on at least one unexpired certificate.
maxSubdomainsPerDomaininteger1000Cap on rows per domain, after sorting. 1–10,000.
maxConcurrencyinteger8Names resolved/checked in parallel. 1–20.
maxRunSecsinteger240Wall-clock budget for the run. 30–3,600.
proxyConfigurationobject{ "useApifyProxy": true }Apify datacenter proxy by default.

Output reference

FieldOnMeaning
hostname, domain, isApex, depthsubdomainThe name, its apex, and how many labels below the apex it sits.
isWildcardsubdomainA wildcard certificate covers names under this host (or this is the wildcard row).
sourcessubdomainWhich sources listed it.
certCount, firstSeen, lastSeensubdomainDistinct certificates naming it; earliest start, latest expiry. 0 / null for a name only HackerTarget knows.
issuerssubdomainIssuing organisations, newest first, ≤ 5 — from crt.sh (the Cert Spotter request used carries no issuer).
dnsStatus, a, aaaa, cname, resolvessubdomainToday's DNS answer. aaaa is null when the AAAA lookup failed. Null when resolveDns is off.
httpStatus, httpFinalUrl, httpTitle, httpServer, httpMs, httpScheme, httpErrorsubdomainThe HTTP check. Null unless checkHttp is on and the host had an address.
subdomainCount … diagnosticTypesdomainThe per-domain summary (see the example above).
error, errorTypediagnosticWhat went wrong.
ok, rowType, input, scrapedAt, source, sourceUrlevery rowBookkeeping; every row has every column, null where it does not apply.

The dataset has five views in Console: Overview, Live check, DNS, Certificates and Per-domain summary.

Pricing

$0.50 per 1,000 subdomains. Pay-per-event, with DNS resolution and the proxy inside that number.

EventWhat triggers itFREEStarterScaleBusiness
Subdomain (primary)One subdomain row written to your dataset$0.0005$0.0005$0.0004$0.0003
HTTP checkOne hostname the HTTP check sent a request to (checkHttp only)$0.0003$0.0003$0.0003$0.0003
Run startedOnce per run, after the first paid row$0.001$0.001$0.001$0.001

Worked example — the prefill. apify.com, DNS on: 36 rows × $0.0005 + $0.001 = $0.019.

Worked example — with the live check. basecamp.com, onlyResolving and checkHttp on: crt.sh lists 75 hostnames; if 40 of them resolve, that is 40 × $0.0005 + 40 × $0.0003 + $0.001 = $0.033, and the 35 that do not resolve are free.

An HTTP check is billed when its request was sent, whether or not the host answered — "nothing listens on 443 or 80" is a result. A host with no DNS address is never checked and never billed for a check.

What you are never charged for

  • the per-domain summary row;
  • every diagnostic row — a source that was down or rate-limited, an entry that was not a domain, a domain with no names, a domain the time budget never reached;
  • names left out by onlyResolving, names past maxSubdomainsPerDomain, and names the run did not reach before maxRunSecs ran out;
  • a run whose domains were usable but produced no subdomain row: it finishes SUCCEEDED with zero results, a status message naming the diagnostic rows ("0 results. 2 diagnostic row(s) explain why — 1 source-unavailable, 1 source-rate-limited. Nothing was charged."), and bills nothing at all, start fee included. A run finishes FAILED only when there was nothing usable to attempt (no domains, none that parsed, no source selected) or the Actor itself hit an error.

Set a maximum total charge on a run (ACTOR_MAX_TOTAL_CHARGE_USD) and the Actor reserves budget for each hostname — the row and, with checkHttp, its check — before resolving it. A name the remaining budget cannot cover is never looked up. The run finishes SUCCEEDED with the ceiling named in its status message, and everything already delivered is yours.

Limits, and the ones that might bite

  • Certificate logs only know names that had a publicly trusted certificate. Internal hosts, hosts covered only by a wildcard certificate, and hosts that never served HTTPS are invisible to them — isWildcard tells you where the logs stop seeing. HackerTarget (opt-in) adds some DNS-seen hosts; nothing here guesses names from a wordlist.
  • crt.sh is slow and sometimes down. 11–16 seconds per domain in our captures, and it can time out on very large domains. An answer past 32 MB is abandoned to protect the run's memory, with a source-unavailable row. Cert Spotter's names still arrive.
  • Cert Spotter shows current certificates and has a small anonymous quota. Every certificate in our capture was unexpired, so its history is short; the response advertised x-ratelimit-limit: 10. A run over many domains will hit it and get source-rate-limited rows for the rest; crt.sh still covers them. Up to ten pages (1,000 certificates) are read per domain.
  • HackerTarget allows a few dozen anonymous queries a day and is off by default. Its IP addresses are not used: every name is resolved fresh.
  • Cross-source certificate matching is by validity window and names. crt.sh and Cert Spotter share no identifier, so certCount treats two certificates with identical validity to the second and identical names under the domain as one. Where several such certificates exist, the source that saw more of them sets the count.
  • DNS is what public resolvers say, from where the run is. Split-horizon names that only resolve inside a company network show nxdomain. CDN-backed names may resolve to different addresses elsewhere.
  • The HTTP check is one GET from a datacenter IP. Some hosts refuse datacenter traffic (a 403 is still recorded as an answer). Only the final URL of a redirect chain is reported, not each hop. Titles are read from HTML only, and only from the first 64 KB.
  • Wildcard rows (includeWildcards) are patterns, so they are never resolved or checked; onlyResolving therefore drops them.
  • The upstream formats may change. crt.sh, Cert Spotter and HackerTarget are free services with no contract; if one changes its output, that source's rows turn into free source-unavailable diagnostics until the Actor is updated, and the other sources keep working.

Use it from an AI agent, or from code

One JSON object in, one flat array out — the shape agent runtimes want. The Actor runs with limited permissions, uses pay-per-event pricing and never enters Standby, so it works over the Apify MCP server and with x402 agentic payments. The Integrations tab pushes results to Slack, a webhook, Zapier, Make, Google Sheets, Snowflake or BigQuery.

curl -X POST "https://api.apify.com/v2/acts/insight.solutions~subdomain-finder-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"domains":["apify.com"],"onlyResolving":true}'
# pip install apify-client
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("insight.solutions/subdomain-finder-api").call(run_input={
"domains": ["basecamp.com"],
"onlyResolving": True,
"checkHttp": True,
})
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
if row["rowType"] != "subdomain":
continue
print(row["hostname"], row["a"], row["httpStatus"], row["httpTitle"])

FAQ

Does it find every subdomain? No tool can promise that. It finds every name that appears on a publicly trusted certificate (crt.sh, Cert Spotter) or in HackerTarget's host index, if you turn it on. Hosts that never had a certificate of their own are the gap; isWildcard shows where a wildcard certificate hides them.

Why do so many names come back nxdomain? Because certificate logs remember everything. 14 of the 36 apify.com names in our capture have had no valid certificate for months or years — integrations that moved, a 2019 www certificate, a test host. firstSeen/lastSeen date them; onlyResolving drops the ones that no longer exist, for free.

Does it scan ports, brute-force names or log in anywhere? No. It reads three public search services and two public DNS resolvers. With checkHttp on, it sends one GET (two at most: https, then http) to each host that has an address. Nothing else touches the target.

What happens when crt.sh is down? You get a free source-unavailable row, Cert Spotter's names — resolved and billed as usual — and a status message that says so. For apify.com that was 20 names instead of 36.

What does isWildcard mean? That a certificate for *.<hostname> exists. Names under it can be served without appearing in any log.

Can I search many domains in one run? Yes. Two are searched at a time, out of courtesy to crt.sh; raise maxRunSecs for long lists. Cert Spotter's anonymous quota will run out on long lists — those domains still get crt.sh's names and a free source-rate-limited row.

Is there any personal data in the output? No. Rows contain hostnames, IP addresses, certificate dates, issuer organisations and, with the HTTP check, a page title and server header. Email identities found on certificates are dropped, and an email address you send as input is recorded as its domain.

  • Public records only. Certificate Transparency logs are public by design: every publicly trusted certificate is logged so that anyone can audit it. DNS answers are public. The Actor never logs in, never sends cookies or credentials, and never uses anybody's API key.
  • The HTTP check touches the target. One or two ordinary GET requests per host. Use it on domains you own or are authorised to assess, and follow the rules of any security programme you work under.
  • Not affiliated with crt.sh, Sectigo, SSLMate (Cert Spotter), HackerTarget, Cloudflare, Google or any company whose hostnames appear in the output. Names and trademarks belong to their owners and are used only to describe which public sources were read.

Our other Actors

Every Insight Solutions Actor is pay-per-result with no browser, no login and no API key, and every one of them returns free diagnostic rows instead of billing for failures. Prices are per 1,000 results.

Video, audio & social

News, documents & the web

Business, finance & jobs

Apps & games