DEV Community

Cizze R
Cizze R

Posted on

How to Build a Domain Intelligence API (WHOIS, DNS, SSL in One Call)

How to Build a Domain Intelligence API

When you're doing lead enrichment, competitor research, or security audits, you usually bounce between four or five different tools. One for WHOIS, one for DNS, one for SSL, one for tech stack. It's slow and the data comes back in five different formats.

The Domain Intelligence Suite consolidates all this into one API call. One request gets you everything.

What comes back

Here's what a lookup for stripe.com looks like:

{
  "domain": "stripe.com",
  "whois": {
    "registrar": "MarkMonitor Inc.",
    "creation_date": "1995-09-17T04:00:00Z",
    "expiration_date": "2030-09-16T04:00:00Z",
    "name_servers": ["ns1.stripe.com", "ns2.stripe.com"]
  },
  "dns": {
    "a": ["54.187.174.202"],
    "mx": ["aspmx.l.google.com"],
    "txt": ["v=spf1 include:_spf.google.com ~all"],
    "ns": ["ns1.stripe.com", "ns2.stripe.com"]
  },
  "ssl": {
    "issuer": "DigiCert",
    "valid_from": "2026-01-15T00:00:00Z",
    "valid_until": "2027-02-15T23:59:59Z",
    "days_remaining": 223
  },
  "tech_stack": {
    "web_server": "nginx",
    "cdn": "Cloudflare",
    "analytics": ["Google Analytics"],
    "javascript_frameworks": ["React"]
  }
}
Enter fullscreen mode Exit fullscreen mode

Using it

import requests, time

API_TOKEN = "YOUR_APIFY_TOKEN"

def domain_intel(domain):
    resp = requests.post(
        "https://api.apify.com/v2/acts/weeknds~domain-intelligence-suite/runs",
        headers={"Authorization": f"Bearer {API_TOKEN}"},
        json={"url": f"https://{domain}"}
    )
    run_id = resp.json()["data"]["id"]
    time.sleep(10)

    items = requests.get(
        f"https://api.apify.com/v2/acts/weeknds~domain-intelligence-suite/runs/{run_id}/dataset/items",
        headers={"Authorization": f"Bearer {API_TOKEN}"}
    ).json()

    return items[0] if items else None

data = domain_intel("stripe.com")
print(f"SSL expires in {data['ssl']['days_remaining']} days")
Enter fullscreen mode Exit fullscreen mode

Node.js version:

async function domainIntel(domain) {
  const TOKEN = process.env.APIFY_TOKEN;
  const runResp = await fetch(
    'https://api.apify.com/v2/acts/weeknds~domain-intelligence-suite/runs',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ url: `https://${domain}` })
    }
  );
  const { data: { id: runId } } = await runResp.json();
  await new Promise(r => setTimeout(r, 10000));
  const itemsResp = await fetch(
    `https://api.apify.com/v2/acts/weeknds~domain-intelligence-suite/runs/${runId}/dataset/items`,
    { headers: { 'Authorization': `Bearer ${TOKEN}` } }
  );
  const items = await itemsResp.json();
  return items[0];
}
Enter fullscreen mode Exit fullscreen mode

Lead enrichment

Feed a list of company domains through it and enrich your CRM:

def enrich_leads(company_domains):
    enriched = []
    for domain in company_domains:
        try:
            data = domain_intel(domain)
            enriched.append({
                "domain": domain,
                "tech_stack": data["tech_stack"],
                "hosting": data["dns"].get("a", []),
                "registrar": data["whois"]["registrar"],
                "domain_age_days": (
                    datetime.now() -
                    datetime.fromisoformat(data["whois"]["creation_date"].replace("Z", "+00:00"))
                ).days
            })
        except Exception as e:
            enriched.append({"domain": domain, "error": str(e)})
    return enriched
Enter fullscreen mode Exit fullscreen mode

SSL monitoring

Check which domains have certificates about to expire:

def monitor_ssl(domains, alert_threshold_days=30):
    alerts = []
    for domain in domains:
        data = domain_intel(domain)
        days_left = data["ssl"]["days_remaining"]

        if days_left < alert_threshold_days:
            alerts.append({
                "domain": domain,
                "days_remaining": days_left,
                "expires": data["ssl"]["valid_until"],
                "severity": "critical" if days_left < 7 else "warning"
            })

    return sorted(alerts, key=lambda x: x["days_remaining"])
Enter fullscreen mode Exit fullscreen mode

Competitor tech stack comparison

See what your competitors are running that you aren't:

def compare_tech_stacks(our_domain, competitor_domains):
    our_stack = set(domain_intel(our_domain)["tech_stack"].keys())
    competitors = {}

    for domain in competitor_domains:
        their_stack = set(domain_intel(domain)["tech_stack"].keys())
        they_have = their_stack - our_stack
        we_have = our_stack - their_stack
        competitors[domain] = {
            "they_use": list(they_have),
            "we_use_exclusively": list(we_have)
        }

    return competitors
Enter fullscreen mode Exit fullscreen mode

A few tips

The actor handles one domain per run. For bulk analysis, fire off multiple parallel calls using Apify's async mode. Cache results for at least 24 hours — WHOIS and DNS data doesn't change minute to minute. Rate limiting is handled automatically.

$0.005 per lookup, so 200 domains costs you a dollar. Commercial domain intelligence APIs charge two to ten times that with usage minimums.

Top comments (0)