# DNS Records Lookup API — Bulk A, MX, TXT, NS, CNAME & CAA (`factpipe/dns-records-lookup`) Actor

Bulk DNS lookups for any list of domains: A, AAAA, MX, TXT, NS, CNAME, SOA and CAA records, plus mail/DNS provider detection, SPF/DMARC presence and TXT verification tokens. No API key. $1.50 per 1,000 domains.

- **URL**: https://apify.com/factpipe/dns-records-lookup.md
- **Developed by:** [Neo B](https://apify.com/factpipe) (community)
- **Categories:** Developer tools, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 domain resolveds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## DNS Records Lookup API — Bulk A, MX, TXT, NS, CNAME, SOA, CAA

**Bulk DNS lookups for any list of domains.** Resolve A, AAAA, MX, TXT, NS, CNAME, SOA and CAA records at scale, plus derived hints you'd otherwise have to build yourself: mail provider (Google Workspace, Microsoft 365, Zoho, Proton, Fastmail, Mimecast, Proofpoint, Amazon SES), authoritative DNS provider (Cloudflare, AWS Route 53, Google Cloud DNS, Azure DNS, GoDaddy, Namecheap, DigitalOcean, Vercel, NS1), SPF/DMARC presence and TXT-based verification tokens (Google, Microsoft, Facebook, Atlassian, Apple, Stripe, DocuSign, Zoom). Public DNS only: no API key, no login, no personal data.

### Quick start

1. Click **Start** with the two prefilled domains (`github.com`, `example.com`). It finishes in seconds.
2. You get one record per domain with A, AAAA, MX, TXT, NS, SOA and CAA records, plus mail provider, DNS provider and SPF/DMARC flags.
3. That first run costs $0.003, well within Apify's free monthly credit. Then paste your own domain list.

### What you get

```json
{
  "query": "github.com",
  "domain": "github.com",
  "found": true,
  "reason": null,
  "a": ["20.205.243.166"],
  "aaaa": [],
  "mx": ["0 github-com.mail.protection.outlook.com"],
  "txt": [
    "MS=6BF03E6AF5CB689E315FB6199603BABF2C88D805",
    "google-site-verification=82Le34Flgtd15ojYhHlGF_6g72muSjamlMVThBOJpks",
    "v=spf1 ip4:192.30.252.0/22 include:spf.protection.outlook.com ... ~all"
  ],
  "ns": [
    "dns1.p08.nsone.net",
    "ns-1283.awsdns-32.org",
    "ns-1707.awsdns-21.co.uk"
  ],
  "cname": null,
  "soa_primary_ns": "ns-1707.awsdns-21.co.uk",
  "soa_serial": 1,
  "soa_minimum_ttl": 86400,
  "caa": ["0 issue \"letsencrypt.org\"", "0 issuewild \"digicert.com\""],
  "mail_provider": "Microsoft 365",
  "dns_provider": "AWS Route 53",
  "has_spf": true,
  "has_dmarc": true,
  "verification_tokens": ["microsoft", "apple", "atlassian", "docusign", "facebook", "google", "stripe"],
  "record_count": 42,
  "source_url": "dns:github.com",
  "fetched_at": "2026-09-15T12:00:00.000Z"
}
```

### Use cases

- **Domain inventory & asset audits**: bulk-resolve every domain you own or manage into one flat table (IPs, mail routing, name servers) for security and compliance reviews.
- **Lead enrichment & sales intelligence**: detect a prospect's email provider (`mail_provider`) and marketing/SaaS stack signals (`verification_tokens`) from public DNS alone — no crawling, no login.
- **DNS migration checks**: confirm A/AAAA, MX and NS records point where they should before and after a cutover, across hundreds of domains at once.
- **Security & vendor risk**: spot domains with no SPF or DMARC (`has_spf`, `has_dmarc`), unexpected CAA issuers, or DNS hosted with an unapproved provider.
- **SaaS & tool discovery**: `verification_tokens` reveals which domains have verified with Google Workspace, Microsoft 365, Atlassian, Stripe, DocuSign, Zoom and more via TXT records.

### Input

| Field | Type | Notes |
|---|---|---|
| `domains` | string\[], required | Domain names, website URLs or email addresses (the host is extracted). Subdomains are kept intact, e.g. `mail.example.com`. Duplicates are looked up once. |
| `recordTypes` | string\[] | Which record types to resolve: any of `A`, `AAAA`, `MX`, `TXT`, `NS`, `CNAME`, `SOA`, `CAA`. Defaults to all eight. Types not selected are returned as `null`. |
| `stripWww` | boolean | If enabled, a leading `www.` is removed before lookup. Off by default — other subdomains are always kept as-is. |

### Pricing (pay per event)

| Event | Price | Meaning |
|---|---|---|
| `domain-resolved` | **$1.50 per 1,000** ($0.0015 each) | One domain that exists and returned at least one requested DNS record. |

Nonexistent, invalid and unreachable domains are never charged. A domain that exists but has zero records of the requested types is delivered but not charged either.

Example: resolving 1,000 domains costs **$1.50**. No start fee. You only pay for delivered results.

### Related factpipe Actors

- [Email Security Checker](https://apify.com/factpipe/email-security-checker) — full SPF/DKIM/DMARC audit with a 0–100 score and fix list (this Actor only reports SPF/DMARC presence as a quick signal; use Email Security Checker for the deep audit).
- [Lighthouse Auditor](https://apify.com/factpipe/lighthouse-auditor) — Lighthouse scores and Core Web Vitals for many pages, mobile or desktop.
- [Sitemap URL Extractor & 404 Checker](https://apify.com/factpipe/sitemap-url-extractor) — extract every URL from XML sitemaps and flag 404s and broken entries.

### FAQ

**What does `null_mx: true` mean?**
The domain publishes an RFC 7505 "null MX" record, explicitly declaring that it accepts no mail. `mx` is then an empty list.

**Why is `cname` usually `null`?**
Most domains (especially apex/root domains) have no CNAME — A/AAAA records are set directly, or via other record types. `cname` is populated for hostnames that are genuinely aliased, e.g. `www.github.com` → `github.com`. When a name has a CNAME, its A/AAAA records resolve through that alias automatically.

**Am I charged for domains that don't exist?**
No. Invalid inputs, nonexistent domains (NXDOMAIN) and DNS failures are returned as not found and never charged. A domain that resolves but has none of the requested record types is also not charged.

**How is `mail_provider` / `dns_provider` detected?**
From well-known hostname patterns in the MX and NS records (e.g. `*.protection.outlook.com` → Microsoft 365, `*.awsdns-*.{com,net,org,co.uk}` → AWS Route 53). Providers outside the detected list, or domains with no matching pattern, return `null`.

**Do you store or expose mailbox addresses found in DNS?**
No. Any mailbox local-part found in a TXT record (e.g. a DMARC `rua=mailto:` reporting address) is masked as `***@domain`.

**Can I call it from Python, JavaScript, Make, Zapier or an AI agent?**
Yes. Run it through the Apify API or official Python/JavaScript clients, connect it to Make, Zapier, n8n, Slack or Google Sheets via Apify integrations, or expose it to AI agents through the Apify MCP server. Input is small and output is deterministic flat JSON.

### Reliability

Deterministic code against public DNS resolvers (1.1.1.1, 8.8.8.8, 9.9.9.9) with automatic retries and backoff on transient failures, structured failure reporting, daily health checks and issue triage.

# Actor input Schema

## `domains` (type: `array`):

Domain names, website URLs or email addresses (the host is extracted). Subdomains are kept intact, e.g. mail.example.com. Duplicates are looked up once.

## `recordTypes` (type: `array`):

Which record types to resolve and return per domain. Types not selected are returned as null.

## `stripWww` (type: `boolean`):

If enabled, a leading "www." is removed before lookup (mail.example.com and other subdomains are always kept as-is).

## Actor input object example

```json
{
  "domains": [
    "github.com",
    "example.com"
  ],
  "recordTypes": [
    "A",
    "AAAA",
    "MX",
    "TXT",
    "NS",
    "CNAME",
    "SOA",
    "CAA"
  ],
  "stripWww": false
}
```

# Actor output Schema

## `resultsDatasetUrl` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "domains": [
        "github.com",
        "example.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("factpipe/dns-records-lookup").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "domains": [
        "github.com",
        "example.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("factpipe/dns-records-lookup").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "domains": [
    "github.com",
    "example.com"
  ]
}' |
apify call factpipe/dns-records-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,factpipe/dns-records-lookup"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/NkEh2R51jHatGtCA3/builds/ATjT0PhL8XKFuOiNn/openapi.json
