crt.sh Subdomain Finder - Certificate Search avatar

crt.sh Subdomain Finder - Certificate Search

Pricing

from $2.00 / 1,000 hosts

Go to Apify Store
crt.sh Subdomain Finder - Certificate Search

crt.sh Subdomain Finder - Certificate Search

Find every subdomain of a domain from public Certificate Transparency logs (crt.sh), one row per host: days until certificate expiry, issuer, environment inferred from the name (staging, dev, production) and first-seen date. Asset inventory, no API key.

Pricing

from $2.00 / 1,000 hosts

Rating

0.0

(0)

Developer

Tom Awake

Tom Awake

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

20 hours ago

Last modified

Share

What does crt.sh Subdomain Finder do?

Every subdomain of a domain, from public Certificate Transparency logs — as an inventory, not a log dump.

Since 2018 browsers reject any TLS certificate that was not published to a public Certificate Transparency log (RFC 6962). That makes CT the most complete public record of which hosts exist under a domain. But it is a log: one entry per certificate issuance event, duplicates included, expired certificates included, with no notion of a "host".

Measured on shopify.com: 8,239 log entries → 5,971 distinct certificates → 627 hosts. A 13:1 reduction. The 627 is the answer; the 8,239 is the raw material.

This Actor does the reduction, and computes the three things the log does not carry: how many days until each host's certificate expires, which environment the hostname belongs to, and when the host was first seen.

No API key. No account. Nothing to break.


What makes this different from querying crt.sh yourself

Four things, each of which cost a measurement to find.

1. One row per host, not per certificate. Certificates are reissued every 90 days, so a host that has existed for three years carries a dozen of them. The inventory merges them: first seen, last issued, certificate count, every issuer ever used, and the expiry date that actually governs the host today.

2. The obvious query silently returns only dead certificates. This is the trap at the centre of this source. On shopify.com:

QueryCertificatesOf which currently validHosts
?q=shopify.com5,2520 (0%)335
?q=shopify.com&exclude=expired2,9902,990 (100%)469
Both, merged8,2392,990627

The two result sets share zero certificate IDs. crt.sh caps each query, and the unfiltered variant returns only historical records. Query it the obvious way and you get an inventory containing not one live host. This Actor runs both and merges them — 627 hosts, 33% more than the better of the two alone.

3. Certificates are logged more than once. Every certificate is logged first as a pre-certificate, then as the final certificate, and often in several logs. The duplicate entries differ only by their crt.sh ID — same serial, same issuer, same dates, same names. Measured inflation: 1.52× on anthropic.com, 1.38× on shopify.com. Rows are deduplicated on (issuer, serial number), the real identity of a certificate, so certificateCount means what it says.

4. Days, not dates. daysUntilExpiry is the column you sort on when you manage an estate. The source gives you 2026-09-26; the question is "how long have I got".


Environment classification

Only the part of the hostname before the searched domain is classified. Without that rule, every host on grafana.com came out as Internal, because grafana is itself the name of an internal-tooling product — the company's own name was contaminating the classification of all its hosts. The root domain says nothing about environment; only the prefix speaks.

The prefix is split into whole tokens — by dots, hyphens and underscores, with trailing digits stripped so staging3 and shell-staging-10 are recognised — and matched against known markers. Priority runs Internal → Staging → Development → Mail, so api-staging.product-internal.example.com is classified Internal: the most sensitive marker wins, not the first one.

Anything with no marker is classified Production. That is deliberate. A public host with a valid certificate is production until proven otherwise, which is both the common case and the prudent assumption for an inventory.

Measured on shopify.com, 627 hosts:

EnvironmentHostsShare
Production44871%
Staging15725%
Mail91%
Internal81%
Development51%

170 of 627 hosts are outside production.


What it is for

  • Asset inventory. Enumerate what actually exists under your domains, including the hosts nobody remembers provisioning.
  • Renewal monitoring. Sort by daysUntilExpiry. A host expiring soon with a high daysSinceLastIssue is a forgotten certificate, not a renewal in progress.
  • Unexpected issuance. issuerCount and issuers show every authority that has ever issued for a host. A new issuer you did not authorise is worth a look.
  • Due diligence. Size an acquisition target's real estate before signing, from public record only.
  • Competitive and market research. Product launches and new regions usually get a certificate before they get an announcement.

This Actor reads a public log. It makes no connection of any kind to the hosts it reports — no port scan, no probe, no DNS resolution, no vulnerability check. Everything returned was published by a certificate authority to a public append-only log, by design, so that it could be audited. Point it at domains you are responsible for, or use it for research; the usual rules about what you do with an inventory still apply.


Pricing: per host, never per row

You are charged per unique host in the output, whatever the output shape. The certificate mode returns several times more rows for the same set of hosts — charging by the row would bill you repeatedly for the same discovery. A run returning 400 certificate rows across 93 hosts is charged 93.

Wildcard entries are charged on their base name, so *.example.com and example.com count once.


Output

One row per host (default)

FieldMeaning
hostnameThe host, or *.domain for a wildcard
environmentProduction / Staging / Development / Internal / Mail
statusValid / Expiring soon (≤30 days) / Expired
daysUntilExpiryDays until the host loses coverage; negative if lapsed
expiresAtDate the latest covering certificate expires
lastIssuedAt, daysSinceLastIssueWhen a certificate was last issued for this host
firstSeenAtEarliest issuance ever logged — the host's age
certificateCountDistinct certificates, after deduplication
currentIssuer, issuers, issuerCountCurrent and historical authorities
subdomainDepth0 for the domain itself, 1 for a direct subdomain
isWildcard, isActiveFlags
currentSerialNumber, crtShUrlIdentifiers for verification

One row per certificate

Adds issuedAt, validityDays (90 signals automated Let's Encrypt, 398 a commercial certificate placed by hand), certificateId, issuerFullName, and coveredNames — every name on the same certificate, which is where hosts you were not looking for tend to appear.

Three dataset views ship with the Actor: Inventory, Renewals due, and Certificates.

The Certificates view shows the six fields above, so it is empty in the default host mode — those fields only exist when there is one row per certificate. Switch mode to certificates before using that view.


Limits

Stated plainly, because they affect what you can conclude.

  • crt.sh caps a single query. The historical half of the result is capped at roughly 5,000 certificates per domain, so for very large domains the expired set is partial. The currently-valid set is retrieved by a separate query and is not affected — if you need completeness, completeness of the live estate is what you get.
  • CT covers publicly-trusted certificates only. Hosts behind a private CA, an internal PKI, or no TLS at all leave no trace here. An empty result is not proof a host does not exist.
  • A logged host is not necessarily reachable. A certificate was issued; whether anything answers on that name today is a different question, and this Actor does not ask it — that would require contacting the host.
  • Environment classification is inferred from the name. It is a heuristic over naming conventions, not ground truth. It is accurate enough to triage a list of 600 hosts and not accurate enough to be evidence.
  • crt.sh is intermittently unavailable. It returns HTTP 502 under load; four consecutive 502s before success were observed while building this. Every request is retried up to six times with exponential backoff, which is why runs occasionally take a minute rather than five seconds.
  • Wildcards hide their contents. *.example.com is one row and an unknown number of real hosts.

Use crt.sh Subdomain Finder as an API

Call it from your own code with the Apify client, here in Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("DataIO/crtsh-subdomain-finder").call(run_input={
'domains': ['shopify.com'],
'mode': 'hosts',
'activeOnly': True,
'maxItems': 500,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

It also works from JavaScript, Make, Zapier, n8n, and from AI agents through the Apify MCP server.

Other actors you might like

FAQ

The actor reads public data from its official source, without logging in and without bypassing any access control. What you do with the data, for example contacting people listed in it, is your responsibility under the laws that apply to you, such as GDPR in Europe.

Can I run it on a schedule?

Yes. Create a schedule in Apify Console, daily or weekly for example, and each run delivers a fresh dataset, which you can send by email, webhook or integration.

Can AI agents use it?

Yes. It is available through the Apify MCP server, and every input field is described in its input schema, so an agent can call it directly.

Source

crt.sh, operated by Sectigo, aggregating the public Certificate Transparency logs. Public, no authentication, no rate limit published. This Actor is not affiliated with Sectigo.