Domain Intelligence

M&A Domain Due Diligence: How to Audit a Company's Domain Portfolio Before You Sign

A pre-close domain audit catches transfer locks, employee-registered domains, renewal cliffs, and DNS delegation drift before they become post-close incidents — with timestamped WHOIS, DNS and SSL evidence in JSON.

July 9, 202612 min readM&A · Due Diligence · WHOIS · DNS · SSL

Introduction

In most acquisitions, the domain portfolio is listed as a line item: the company owns the brand, the websites, and the customer login domain. In practice, domain assets drift. Marketing buys ccTLDs through agencies. Engineers register product domains on personal accounts. A registrar transfer happens during a rebrand. A renewal date quietly moves into the first 90 days after close.

The failure mode is predictable: a post-close outage, a legal scramble over who controls the registrar account, or a domain that cannot be consolidated because an unexpected EPP lock blocks transfer. A focused, API-backed domain due diligence pass can be done in under an hour and produces timestamped evidence legal and technical teams can attach to the deal record.

This article is the deep dive for use case 6 in the WHOIS API use cases guide. It is not a general domain inventory tutorial and not a long-term monitoring playbook.

Scope boundary: pre-close diligence is a snapshot workflow. For steady-state ownership and renewal operations, use the domain portfolio management guide. For building the first dataset, start with the domain inventory API workflow.

What Is M&A Domain Due Diligence?

M&A domain due diligence is a structured review of a target's externally visible domain signals before signing: registrar, registrant context when available, expiration dates, EPP status codes, nameserver delegation, and — for customer-facing domains — SSL certificate health.

Practical definition: you are not trying to prove the target is secure in general. You are trying to answer four questions before close: who can renew the domain, who can transfer it, what can expire during integration, and whether DNS control matches what the deal memo claims.

WhoisJSON supplies the lookup layer through documented REST endpoints. Your diligence system stores the normalized output with a timestamp so legal, IT, and integration teams can triage blockers before Day 0.

Why Pre-Close Domain Audits Fail Without API Evidence

Deal teams often rely on a domain list from the seller, a registrar export, or screenshots from a WHOIS website. Those sources are slow to reconcile, hard to timestamp, and easy to misread across TLDs. An API workflow makes the audit reproducible: the same domain list produces the same JSON structure every time the check is rerun.

Ownership drift

Domains registered to employees, agencies, or former subsidiaries block clean registrar consolidation after close.

Transfer blockers

Unexpected EPP locks and holds can delay registrar moves when you need them most. See the EPP status codes reference.

Renewal cliffs

Expiry inside the integration window creates outage risk during the most fragile operating period. See domain expiry lifecycle detection.

DNS control mismatch

WHOIS/RDAP nameservers that do not match live NS records suggest the zone is controlled elsewhere than expected.

Red Flags to Track Before Signing

A useful diligence pass focuses on issues that can block transfers, break continuity, or create immediate operational risk — not on generic security posture scoring.

Red flagEndpointFields to readWhy it matters
Registrant org does not match target entity/whoiscontacts, registrarOwnership disputes delay transfers and renewals.
Expiration inside 90–180 days post-close/whoisexpires, expiration.daysLeftRenewals during integration are a common outage source.
Unexpected transfer lock or hold/whoisstatus, statusAnalysisLocks can block registrar consolidation or emergency response.
WHOIS nameservers ≠ live DNS delegation/whois + /nslookupnameserver, NS, nsAnalysisThe zone may be controlled by an unknown DNS provider.
Customer-facing domain with invalid or near-expiry SSL/ssl-cert-checkvalid, valid_to, issuerCertificate incidents become revenue and trust incidents.

Which WhoisJSON Endpoints to Use

The workflow below uses only documented endpoints from the WhoisJSON OpenAPI specification. Authenticate every request with Authorization: TOKEN=YOUR_API_KEY and use the production base URL https://whoisjson.com/api/v1.

Diligence signalEndpointFields to readUse
Registrar and ownership context/whoisregistrar, contacts, createdConfirm administrative control and entity alignment.
Expiry and transfer readiness/whoisexpires, expiration, status, statusAnalysisFlag renewal cliffs and transfer blockers.
Live DNS delegation/nslookupNS, SOACompare against WHOIS nameservers and expected provider.
Production HTTPS posture/ssl-cert-checkvalid, valid_to, issuer, detailsCheck login, app, and customer-facing endpoints only.

For field-level semantics, see the WHOIS API JSON response reference. For registrar-specific workflows, see the registrar lookup API guide.

Pre-Close Workflow in Four Steps

Treat diligence like evidence collection, not like security scanning. Each step produces fields you can attach to the deal record.

Step 1 — Collect the domain list

Start from the seller's asset schedule, public product links, OAuth callback domains, support email domains, ccTLDs, redirect domains, and any domain referenced in contracts or marketing materials. If the list is large, use the  a(href="/blog/bulk-whois-api-multiple-domains") bulk WHOIS lookup guide | to pace parallel requests within your plan.

Step 2 — Query WHOIS/RDAP for every domain

Capture registrar, created and expires dates, EPP status, nameserver fields, and registrant organization when visible. Compare registrant organization against the target legal entity name. Flag domains expiring inside your integration window using code expiration.daysLeft | when available.

Step 3 — Confirm DNS delegation

Query /nslookup and compare NS against WHOIS/RDAP nameservers. A mismatch does not always mean fraud, but it should be documented before close. For ongoing delegation monitoring after close, see nameserver monitoring.

Step 4 — Check SSL on customer-facing domains only

Use /ssl-cert-check for login, app, API, and marketing domains where a certificate incident would be visible to users. Skip parked or redirect-only names unless they terminate HTTPS.

Example Diligence Report Schema

Legal teams need a list of issues. Technical teams need evidence. Store raw responses if required, but normalize each domain into one row you can sort, filter, and export.

Normalized diligence rowJSON
{
  "domain": "example.com",
  "checked_at": "2026-07-09T09:00:00Z",
  "registrar": "Example Registrar, Inc.",
  "created": "2014-03-21 00:00:00",
  "expires": "2026-09-02 00:00:00",
  "days_left": 55,
  "epp_status": ["clientTransferProhibited"],
  "risk": {
    "level": "medium",
    "reasons": [
      "expires_in_integration_window",
      "transfer_lock_present"
    ]
  },
  "delegation": {
    "dns_ns": ["ns1.dns-provider.com", "ns2.dns-provider.com"],
    "whois_ns": ["ns1.dns-provider.com", "ns2.dns-provider.com"],
    "matches": true
  },
  "ssl": {
    "checked": true,
    "valid": true,
    "issuer": "DigiCert Inc",
    "valid_to": "2026-12-10T23:59:59.000Z"
  }
}

Add an internal code criticality | field from your deal team — SSO, email, production web, redirect only — so renewal and SSL findings are prioritized correctly.

Basic Requests

A minimum viable diligence pass usually starts with two calls per domain. Add SSL only where user-facing HTTPS matters.

WHOIS/RDAP evidencecURL
curl "https://whoisjson.com/api/v1/whois?domain=example.com" \
  -H "Authorization: TOKEN=YOUR_API_KEY"
DNS delegation evidencecURL
curl "https://whoisjson.com/api/v1/nslookup?domain=example.com" \
  -H "Authorization: TOKEN=YOUR_API_KEY"
SSL evidence (customer-facing domains)cURL
curl "https://whoisjson.com/api/v1/ssl-cert-check?domain=example.com" \
  -H "Authorization: TOKEN=YOUR_API_KEY"

Python Example: Audit a Domain List Before Close

This example reads a target domain list, fetches WHOIS and DNS evidence for every name, optionally checks SSL for customer-facing domains, and returns normalized diligence rows. In production, persist results and add retry/backoff for 429 responses.

ma_domain_diligence.pyPython
import json
import requests
from datetime import datetime, timezone

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://whoisjson.com/api/v1"
HEADERS = {"Authorization": f"TOKEN={API_KEY}"}


def get_json(path, domain):
    response = requests.get(
        f"{BASE_URL}/{path}",
        headers=HEADERS,
        params={"domain": domain},
        timeout=20,
    )
    response.raise_for_status()
    return response.json()


def normalize_domain(domain, ssl_check=False, integration_window_days=90):
    whois = get_json("whois", domain)
    dns = get_json("nslookup", domain)

    registrar = (whois.get("registrar") or {}).get("name")
    expiration = whois.get("expiration") or {}
    days_left = expiration.get("daysLeft")
    status = whois.get("status") or []

    dns_ns = dns.get("NS") or []
    whois_ns = whois.get("nameserver") or []
    ns_matches = sorted([x.lower() for x in dns_ns]) == sorted([x.lower() for x in whois_ns])

    reasons = []
    if days_left is not None and days_left <= integration_window_days:
        reasons.append("expires_in_integration_window")
    if any("transferprohibited" in s.lower() for s in status):
        reasons.append("transfer_lock_present")
    if dns_ns and whois_ns and not ns_matches:
        reasons.append("whois_dns_delegation_mismatch")

    level = "low"
    if "whois_dns_delegation_mismatch" in reasons:
        level = "high"
    elif reasons:
        level = "medium"

    row = {
        "domain": domain,
        "checked_at": datetime.now(timezone.utc).isoformat(),
        "registrar": registrar,
        "created": whois.get("created"),
        "expires": whois.get("expires"),
        "days_left": days_left,
        "epp_status": status,
        "risk": {"level": level, "reasons": reasons},
        "delegation": {
            "dns_ns": dns_ns,
            "whois_ns": whois_ns,
            "matches": ns_matches,
        },
        "ssl": {"checked": False},
    }

    if ssl_check:
        ssl = get_json("ssl-cert-check", domain)
        issuer = ssl.get("issuer") or {}
        row["ssl"] = {
            "checked": True,
            "valid": ssl.get("valid"),
            "issuer": issuer.get("O") or issuer.get("CN"),
            "valid_to": ssl.get("valid_to"),
        }

    return row


domains = ["example.com", "example.org"]
report = [normalize_domain(d, ssl_check=True) for d in domains]
print(json.dumps(report, indent=2))

Every response includes the Remaining-Requests header. For larger target portfolios, use the rate limits and retries guide.

Node.js Example: Export a Due Diligence JSON Report

The same normalization pattern works in Node.js when your diligence tooling already runs in JavaScript.

ma-domain-diligence.jsNode.js
const API_KEY = "YOUR_API_KEY";
const BASE_URL = "https://whoisjson.com/api/v1";

async function getJson(path, domain) {
  const url = new URL(`${BASE_URL}/${path}`);
  url.searchParams.set("domain", domain);

  const response = await fetch(url, {
    headers: { Authorization: `TOKEN=${API_KEY}` },
  });

  if (!response.ok) {
    throw new Error(`${path} failed with ${response.status}`);
  }

  return response.json();
}

function sorted(values) {
  return [...new Set((values || []).map((v) => String(v).toLowerCase()))].sort();
}

async function auditDomain(domain, { sslCheck = false } = {}) {
  const whois = await getJson("whois", domain);
  const dns = await getJson("nslookup", domain);

  const status = whois.status || [];
  const dnsNs = dns.NS || [];
  const whoisNs = whois.nameserver || [];
  const nsMatches = JSON.stringify(sorted(dnsNs)) === JSON.stringify(sorted(whoisNs));

  const reasons = [];
  if ((whois.expiration?.daysLeft ?? 999) <= 90) {
    reasons.push("expires_in_integration_window");
  }
  if (status.some((s) => String(s).toLowerCase().includes("transferprohibited"))) {
    reasons.push("transfer_lock_present");
  }
  if (dnsNs.length && whoisNs.length && !nsMatches) {
    reasons.push("whois_dns_delegation_mismatch");
  }

  const row = {
    domain,
    checked_at: new Date().toISOString(),
    registrar: whois?.registrar?.name || null,
    expires: whois?.expires || null,
    days_left: whois?.expiration?.daysLeft ?? null,
    epp_status: status,
    delegation: { dns_ns: dnsNs, whois_ns: whoisNs, matches: nsMatches },
    risk: {
      level: reasons.includes("whois_dns_delegation_mismatch") ? "high" : reasons.length ? "medium" : "low",
      reasons,
    },
    ssl: { checked: false },
  };

  if (sslCheck) {
    const ssl = await getJson("ssl-cert-check", domain);
    row.ssl = {
      checked: true,
      valid: ssl?.valid,
      issuer: ssl?.issuer?.O || ssl?.issuer?.CN || null,
      valid_to: ssl?.valid_to || null,
    };
  }

  return row;
}

async function main() {
  const domains = ["example.com", "example.org"];
  const report = [];
  for (const domain of domains) {
    report.push(await auditDomain(domain, { sslCheck: true }));
  }
  console.log(JSON.stringify(report, null, 2));
}

main().catch(console.error);

Turn Findings Into Day 0 Actions

The best diligence output is not a static PDF. It is a task list with owners and deadlines aligned to the integration plan.

  • Transfer blockers: escalate EPP locks and registrar account access to the seller before close. Fixing these post-close is slower and riskier.
  • Renewal cliffs: renew critical domains pre-close or negotiate an escrow process so renewals cannot be missed during transition.
  • DNS ownership: document the authoritative DNS provider for Day 0 and capture nameserver management access as a deliverable.
  • Customer-facing SSL risk: ensure certificate issuance and renewal are not tied to an employee mailbox or abandoned vendor account.

After close, move from diligence snapshots to continuous monitoring with Domain Monitoring and the domain portfolio management workflow.

Limits and Non-Goals

A good diligence workflow is explicit about what public domain data can and cannot prove.

  • WHOIS/RDAP provides administrative evidence, not legal title. Treat it as operational proof of who controls renewal and DNS today.
  • This article does not replace legal review, IP assignment checks, or registrar account access validation.
  • Lookup endpoints return current data. Store your own snapshots if the deal timeline spans weeks.
  • SSL checks inspect the certificate currently served on supported HTTPS ports; they do not audit internal infrastructure.
  • Vendor-facing third-party risk reviews are a different workflow. See the vendor domain security audit checklist when evaluating SaaS suppliers rather than acquisition targets.

FAQ

What domains should be included in an M&A domain audit?

Include brand domains, customer login and SSO domains, API and documentation domains, redirect and marketing campaign domains, and any ccTLDs. If a domain appears in product links, customer emails, OAuth callbacks, or legal notices, it belongs in the diligence list.

Can WHOIS and RDAP data prove ownership?

WHOIS/RDAP provides strong administrative evidence such as registrar, dates, status codes, and nameservers, and sometimes registrant details. Treat it as operational evidence of who controls renewal and DNS today, not as a legal deed.

How often should diligence checks run?

Pre-close diligence is usually a snapshot. If signing is delayed, rerun the audit weekly on critical domains and daily on anything expiring inside 30 days.

What is the fastest minimum viable audit?

Start with registrar, expiry date, and EPP status from /whois, then confirm DNS delegation via /nslookup. Add /ssl-cert-check only for customer-facing domains and login endpoints where certificate incidents would be visible to users.

How many API calls does a diligence pass need?

A minimum pass uses two calls per domain for WHOIS and DNS. Adding SSL for customer-facing domains brings the total to three calls per domain. For 50 domains, that is 100 to 150 API calls depending on SSL coverage.

Conclusion

Domain assets are business-critical infrastructure, but they are often treated as paperwork until something breaks after close. A lightweight API-based diligence pass turns them into evidence: who controls the registrar, what can block a transfer, what can expire during integration, and whether DNS delegation matches the operating model you are buying.

Start with the seller's domain list, normalize WHOIS and DNS evidence into one report row per domain, escalate blockers before signing, then hand the portfolio to monitoring and portfolio management workflows on Day 0.

Run a pre-close domain audit

Query WHOIS, DNS and SSL evidence as structured JSON. Export a report, assign owners, and remove transfer and renewal risk before close.

Start freeBulk WHOIS guide
Domain Intelligence

Audit a Target's Domain Portfolio Before You Sign

Query WHOIS/RDAP, DNS delegation and SSL certificate evidence with one API key, then export timestamped diligence rows legal and technical teams can act on.

Transfer lock detectionExpiry riskDNS delegation checks1,000 free requests/month