Subdomain Finder, crt.sh Certificate Transparency Logs Search avatar

Subdomain Finder, crt.sh Certificate Transparency Logs Search

Pricing

from $2.20 / 1,000 result rows

Go to Apify Store
Subdomain Finder, crt.sh Certificate Transparency Logs Search

Subdomain Finder, crt.sh Certificate Transparency Logs Search

Subdomain finder past the crt.sh query limits: 7,236 subdomains of mercedes-benz.com where one crt.sh query returns 4. Certificate transparency logs search with duplicates merged, expiring and self-signed certificates flagged, and a watch mode for new certificates.

Pricing

from $2.20 / 1,000 result rows

Rating

0.0

(0)

Developer

Snow Leo Data

Snow Leo Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

Find every subdomain and every SSL/TLS certificate ever logged for a domain, from the public Certificate Transparency search at crt.sh. Get expiry dates, issuers, serial numbers, suspicious host names (dev, staging, vpn, admin) and a per-domain summary. Watch a list of domains and get only what is new since the last run.

What makes this actor different is not the source. It is what happens when crt.sh quietly returns less than it has.

Why a plain crt.sh query is not enough

crt.sh is free and excellent, but it loses data in three ways, and none of them produces an error:

  1. Hyphenated domains lose their subdomains. crt.sh's default search splits the name at the hyphen. For coca-cola.com a plain query returns 3 host names. Asked with a pattern match instead, the same single query returns 666, and it is cut too (its newest entry is from 2021-10-08). With slicing this actor returns 1,271 host names.
  2. Large domains are cut, and the newest certificates are the ones cut. There is no pagination (limit and offset are ignored). When a domain has more than roughly 10000 matching names, crt.sh answers HTTP 200 with only the oldest certificates. For github.io the plain query's newest certificate is from 2021-10-16, although valid certificates from this year exist.
  3. Heavy queries time out, and the timeout looks like "not found". When its database gives up after about 60 seconds, crt.sh answers HTTP 404, the same status a missing page gets.

This actor detects each case and works around it by slicing: it asks for the currently valid certificates separately, detects a cut answer, and then walks the domain zone by zone (api.example.com, mail.example.com, ...), adding zones it discovers along the way, until the answer is whole or your limit is reached.

Measured: one crt.sh query versus this actor

Same day, same source, default limit of 40 queries per domain. Host names are unique names that belong to the domain.

DomainOne plain queryThis actorQueries
mercedes-benz.com4 host names, 98 certificates7,236 host names, 23,080 certificates40
coca-cola.com3 host names, 203 certificates1,271 host names, 3,558 certificates40
microsoft.com3,778 host names, 5,827 certificates10,804 host names, 37,266 certificates40
github.io329 host names, 2,558 certificates345 host names, 3,281 certificates40
apify.com40 host names, 515 certificates40 host names, 515 certificates2

The last row matters as much as the others: a small domain needs only 2 queries. The default input (apify.com) finished on the Apify platform with 41 rows in 9.2 seconds. Slicing only starts when crt.sh actually cut the answer.

All four large domains stopped at the 40-query limit and are reported as partial in their summary row. Raise maxQueriesPerDomain to go further.

Reproduce: python3 tools/measure.py mercedes-benz.com.

What you get

Choose with output:

  • Subdomains (default): one row per unique host name, with first and last time it appeared in a certificate, how many certificates named it, which issuers, the latest expiry date, days left, status, and whether a label looks sensitive.
  • Certificates: one row per unique certificate. crt.sh logs most certificates twice (a precertificate and the final certificate, with different ids). They are merged: apify.com has 980 log entries but only 515 certificates.
  • Both.

Every domain also gets a summary row: counts of valid, expiring, expired and self-signed certificates, issuer shares, the list of suspicious subdomains, other domains that share certificates with this one, and how completely crt.sh answered (complete, sliced, partial, failed) with the reason.

Example subdomain row from a real run:

{
"record_type": "subdomain",
"domain": "apify.com",
"hostname": "*.preview.docs.apify.com",
"is_wildcard": true,
"subdomain_level": 2,
"first_seen": "2025-06-24T00:00:00Z",
"last_seen": "2026-05-25T00:00:00Z",
"certificate_count": 2,
"issuers": ["Amazon"],
"latest_not_after": "2026-12-08T23:59:59Z",
"days_to_expiry": 82,
"status": "VALID",
"has_valid_certificate": true,
"latest_issuer": "Amazon",
"latest_serial_number": "0a076daa9e1ca93acb16d1dd52e700ca",
"latest_crtsh_url": "https://crt.sh/?id=26620732136",
"is_suspicious": true,
"suspicious_keywords": ["preview"],
"suspicious_categories": ["environment"]
}

The dataset has 4 views in the Apify Console: Subdomains, Certificates, Domain summary and Errors.

Useful findings, not just raw rows

  • Expired and expiring certificates. status is VALID, EXPIRING, EXPIRED or NOT_YET_VALID. EXPIRING means within expiringWithinDays (default 30).
  • Suspicious host names. 5 categories and 73 built-in keywords: environments (dev, staging, uat, preview), remote access (vpn, admin, sso, owa, citrix), DevOps (jenkins, gitlab, grafana, argocd), data (db, backup, ftp, phpmyadmin) and internal (intranet, corp, legacy). A keyword must equal a whole label part, so devices.example.com and adminton.example.com are not flagged. Add your own with suspiciousKeywords.
  • Issuer shares. Which certificate authorities issue for the domain and what share each has.
  • Self-signed certificates. Detected from the issuer. With fetchFingerprints on, detected exactly from the certificate bytes.
  • Related domains. Other registrable domains named in the same certificates, often sister brands or old names.
  • Fingerprints (optional). fetchFingerprints downloads certificates and adds SHA256 and SHA1 fingerprints, key algorithm and size, and signature algorithm. The final certificate is preferred over the precertificate, because only the final certificate's fingerprint matches what a server presents.

Monitor mode: only what is new

Turn on monitorMode and schedule the actor, for example daily. The first run delivers everything and remembers it. Every later run delivers only certificates and host names that were not delivered before, marked change_type: NEW, plus the summary row with new_certificates and new_hostnames.

  • Memory is kept in a named storage per monitorName, so several schedules do not interfere.
  • Only rows that actually reached your dataset are remembered. If your spending limit stops a run halfway, the rows you did not get are still new next time.
  • Certificate Transparency is append-only, so a change is always an addition: a new certificate, a new host name.

Batch checks

Put any number of domains into domains. URLs, e-mail addresses and *. prefixes are cleaned (https://www.example.com/path becomes example.com). Duplicates are removed. Domains are processed one after another, because crt.sh blocks parallel requests.

When crt.sh does not answer

crt.sh is a free public service and is often slow or overloaded. What we measured:

  • Parallel requests fail. Four requests at once got HTTP 429, 502 and HTML error pages instead of JSON for every query. The actor sends one request at a time with at least 2 seconds between them.
  • Very large domains time out. microsoft.com: the query for its currently valid certificates got no answer in 90 seconds, twice in a row (186.9 seconds in total). In another measurement crt.sh answered the same query with HTTP 404 after about 60 seconds.
  • Large domains are cut. github.io's plain query returned 5,055 log entries, oldest first, ending at 2021-10-16. Its 49 currently valid certificates were all missing from it.
  • Load changes by the minute. In our microsoft.com measurement, 2 of 40 queries failed and the rest answered.

What the actor does about it:

  • A fast failure (429, 5xx, an HTML page, a quick 404) is retried after cooling down 6, 15 and 30 seconds.
  • A slow failure (a timeout, or a 404 after 30 seconds or more) is not retried, because the same query dies the same way. That part of the domain is split into zones instead.
  • After 4 failures in a row the domain stops, so one broken domain cannot burn an hour of your run.
  • maxQueriesPerDomain (default 40) and maxMinutesPerDomain (default 15) cap the work per domain.

You never get a silent empty result. If nothing could be read for a domain, the dataset gets an error row with error_code and error_message, for example SOURCE_GAVE_UP or SOURCE_TIMEOUT. Error rows are not charged. If some queries failed but others worked, you get the data plus a summary row with completeness: partial and failure_reason. The run report (REPORT in the key-value store) lists every crt.sh query with its status, rows, new rows and time.

Input

FieldDefaultWhat it does
domainsapify.comDomains to search, subdomains included.
outputsubdomainssubdomains, certificates or both.
filterallall, valid, expiring, expired, suspicious, wildcard. The summary row is always delivered.
includeSummarytrueOne summary row per domain.
expiringWithinDays30Window for EXPIRING, from 1 to 825 days.
suspiciousKeywordsemptyExtra keywords.
replaceDefaultKeywordsfalseUse only your keywords.
monitorModefalseDeliver only what is new since the last run.
monitorNamedefaultSeparate memory per watchlist.
emitSeenInMonitorfalseIn monitor mode, also deliver rows seen before (change_type: SEEN).
fetchFingerprintsfalseDownload certificates for fingerprints and key details.
maxFingerprintsPerDomain25Cap for the downloads, valid certificates first.
includeSubdomainstrueOff: exact domain only.
includeExpiredtrueOff: currently valid certificates only, one query per domain.
sliceLargeDomainstrueOff: no slicing.
maxQueriesPerDomain40From 2 to 400.
maxMinutesPerDomain15From 1 to 180.
maxRowsPerDomain00 means no limit.
compactOutputfalseDrop empty fields and long id lists, for AI agents and spreadsheets.
requestTimeoutSecs70Per request, from 15 to 180. crt.sh itself gives up after about 60 seconds.

Compared with other crt.sh actors in the Store

Checked on the public Store pages and input schemas:

  • None of them handles the hyphen split, the silent cut or the 404-on-timeout. A single query per domain returns 4 host names for mercedes-benz.com where this actor returns 7,236.
  • They return log entries, so most certificates appear twice. This actor merges them.
  • Monitor mode, suspicious host names, issuer shares, related domains, fingerprints and named error rows are here in one actor.
  • ryanclinton/crt-sh-search adds risk scores, typosquat detection and executive summaries. This actor does not score risk or look for look-alike domains. If that is what you need, use that actor.

Honest limits

  • crt.sh is the only source. Subdomains that never had a publicly trusted certificate (internal names, names covered only by a wildcard) are not in Certificate Transparency and will not be found. Tools that also use DNS brute force or passive DNS find more names, and fewer of them are verified by a certificate.
  • Large domains are slow. crt.sh answers one query in seconds to a minute. 40 queries took between 449.7 and 656.6 seconds per large domain in our measurements. The number of queries, not rows, sets the run time.
  • Partial is normal for very large domains. microsoft.com had 2 of 40 queries fail and still stopped at the limit. The summary row says so.
  • No DNS resolution or HTTP probing. A host name in a certificate does not mean it resolves today. has_valid_certificate is the closest signal.
  • Self-signed detection without fingerprints compares issuer and subject common names. Publicly logged certificates are almost never self-signed, so this is usually zero.

FAQ

How is this different from opening crt.sh in a browser?

The browser shows the same cut result. This actor detects the cut, slices the search, merges duplicate log entries, and turns certificates into subdomain rows with expiry status.

Do I need an API key or a proxy?

No. crt.sh is public. The actor uses no proxy and no browser.

Why did my run take several minutes for one domain?

The domain was large enough for crt.sh to cut or time out, so the actor sliced it. The summary row shows source_truncated, queries_made and rows_from_single_query. Lower maxQueriesPerDomain for faster, less complete runs.

Why did a domain return an error row?

crt.sh did not answer for that domain. The row names the reason. You were not charged for it. Try again later, or lower the load by giving fewer domains per run.

Can I track new subdomains of my competitors or my own company?

Yes. Turn on monitorMode, put the domains into domains, and schedule the actor daily. You will get only new host names and certificates.

Does it find wildcard certificates?

Yes. Wildcard names keep their *. prefix and have is_wildcard: true. Use filter: wildcard to get only those.

What else is this called?

Other names for this job: phishing subdomain detection, shadow IT discovery, apex domain detection, CT log monitoring, certificate validity days. The fields behind them are is_suspicious, related_domains, is_apex, log_entries and validity_days.