# Bulk DNS & Domain Checker — Records, WHOIS & Expiry (`haketa/bulk-dns-checker`) Actor

Check thousands of domains at once: A/AAAA/MX/TXT/NS records, SPF/DMARC/DKIM, mail provider, registrar, creation & expiry dates, nameservers and DNSSEC. Fast, cheap, keyless DNS & domain lookup for IT, security and domain portfolios.

- **URL**: https://apify.com/haketa/bulk-dns-checker.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Bulk DNS & Domain Checker — Records, Mail, WHOIS & Expiry

Look up the DNS and domain details of **thousands of domains at once.** Paste a list and get, for each one: **A/AAAA/MX/TXT/NS records, SPF/DMARC/DKIM, detected mail provider, registrar, creation & expiry dates, days-until-expiry and DNSSEC.**

Fast, cheap and keyless — the DNS and domain intelligence you need for **IT, email deliverability, security and domain portfolio management.**

***

### Why this Actor?

DNS holds the answers to a lot of important questions: does this domain resolve, where does its mail go, is SPF/DMARC set up, who is the registrar, and when does it expire? Checking one domain is easy; checking a whole portfolio or prospect list is not. This Actor does it in bulk on plain DNS + RDAP, so it's fast and inexpensive at scale.

- **Domain portfolio monitoring** — track expiry dates across all your domains and never miss a renewal.
- **Email deliverability audits** — check MX, SPF, DMARC and DKIM across a list of domains.
- **Security & recon** — map nameservers, mail providers and DNSSEC.
- **Lead enrichment** — add mail provider and registrar signals to a list of company domains.

***

### What you get

One record per domain:

| Field | Description |
| --- | --- |
| `domain` | The domain |
| `resolves` | Whether it resolves (has A/AAAA) |
| `aRecords` / `aaaaRecords` | IPv4 / IPv6 addresses |
| `mxRecords` | Mail servers (priority order) |
| `mailProvider` | Detected provider (Google Workspace, Microsoft 365…) |
| `nsRecords` | Nameservers |
| `hasSpf` / `hasDmarc` / `hasDkim` | Email-auth records present |
| `txtRecords` | TXT records |
| `registrar` | Domain registrar (via RDAP) |
| `createdDate` / `expiryDate` | Registration & expiry dates |
| `daysUntilExpiry` | Days until the domain expires |
| `dnssec` | Whether DNSSEC is enabled |
| `error` | Error, if the domain doesn't resolve |
| `scrapedAt` | Timestamp |

***

### Example output

```json
{
  "domain": "github.com",
  "resolves": "true",
  "aRecords": "140.82.121.4",
  "mxRecords": "github-com.mail.protection.outlook.com",
  "mailProvider": "Microsoft 365",
  "nsRecords": "dns1.p08.nsone.net, dns2.p08.nsone.net",
  "hasSpf": "true",
  "hasDmarc": "true",
  "registrar": "MarkMonitor Inc.",
  "createdDate": "2007-10-09",
  "expiryDate": "2026-10-09",
  "daysUntilExpiry": "92",
  "dnssec": "false",
  "scrapedAt": "2026-07-09T15:00:00.000Z"
}
```

***

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `domains` | array | — | **Required.** Domains to check. URLs and emails are accepted too (the domain is extracted). |
| `whoisLookup` | boolean | `true` | Look up registrar, expiry and DNSSEC via RDAP. Turn off for a faster, DNS-only run. |
| `maxConcurrency` | integer | `50` | Domains checked in parallel. |

#### DNS-only (fastest)

```json
{ "domains": ["example.com", "github.com"], "whoisLookup": false }
```

#### Full check with WHOIS

```json
{ "domains": ["example.com", "mysite.com"], "whoisLookup": true }
```

***

### Use cases in detail

#### 1. Domain expiry monitoring

Run your whole portfolio and sort by `daysUntilExpiry` to catch domains that need renewing — schedule it to get an ongoing watch.

#### 2. Email deliverability audit

Check `mxRecords`, `hasSpf`, `hasDmarc` and `mailProvider` across your domains (or a client's) to find gaps that hurt deliverability.

#### 3. Security & infrastructure recon

Map nameservers, DNSSEC and mail providers across a set of domains for an infrastructure overview.

#### 4. Lead enrichment

Add `mailProvider` and `registrar` to a list of company domains as B2B signals.

***

### How to use it

1. Click **Try for free**.
2. Paste your domains.
3. Click **Start**.
4. Export as **JSON, CSV, Excel**, or via the Apify API.

DNS is very fast; enabling WHOIS adds a lookup per domain, so DNS-only runs are quickest on huge lists.

***

### Calling from the API

```bash
curl -X POST "https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "domains": ["github.com", "example.com"], "whoisLookup": true }'
```

Then fetch the dataset (JSON/CSV):

```bash
curl "https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs/last/dataset/items?token=YOUR_APIFY_TOKEN&format=csv"
```

***

### Frequently asked questions

**What records does it check?**
A, AAAA, MX, NS and TXT, plus SPF/DMARC/DKIM detection — and, with WHOIS on, registrar, creation/expiry dates and DNSSEC.

**Why is the registrar/expiry sometimes empty?**
Registrar data comes from RDAP, and not every TLD publishes RDAP yet (many newer TLDs don't). DNS fields are always populated when the domain resolves.

**Can I pass URLs or emails instead of bare domains?**
Yes — the domain is extracted automatically (e.g. `https://www.site.com/page` and `user@site.com` both become `site.com`).

**How many domains can it handle?**
Thousands to millions. DNS-only is fastest; WHOIS adds an RDAP request per domain.

**How is the mail provider detected?**
From the MX host (e.g. `*.protection.outlook.com` → Microsoft 365, `aspmx.l.google.com` → Google Workspace).

***

### Tips

- **Turn off `whoisLookup`** for the fastest possible run on huge lists (DNS-only).
- **Sort by `daysUntilExpiry`** for renewal monitoring.
- **Filter `hasSpf` / `hasDmarc` = false** to find email-auth gaps.

***

### Notes

This Actor performs public DNS and RDAP lookups on the domains you provide. It reads publicly available records only. Use on domains you have a legitimate reason to check.

***

### Support

Want CAA/SRV records, blacklist checks, or SSL certificate details? Open an issue from the Actor's page.

# Actor input Schema

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

Paste the domains you want to check, one per line (e.g. example.com). Handles a few or thousands at once. URLs and email addresses work too — the domain is pulled out automatically. Leave empty to run a quick demo on a few popular domains.

## `whoisLookup` (type: `boolean`):

Also look up the registrar, creation & expiry dates and DNSSEC for each domain. Turn this off for a faster, DNS-only check.

## `maxItems` (type: `integer`):

Safety cap on how many domains are checked in one run. Set to 0 for no limit.

## `maxConcurrency` (type: `integer`):

How many domains to check at the same time. Higher is faster; the default is a good balance.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. Off by default — this check needs no proxy.

## Actor input object example

```json
{
  "domains": [
    "github.com",
    "google.com",
    "cloudflare.com"
  ],
  "whoisLookup": true,
  "maxItems": 100,
  "maxConcurrency": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `domain` (type: `string`):

The domain

## `resolves` (type: `string`):

Whether it resolves (has A/AAAA)

## `aRecords` (type: `string`):

IPv4 addresses

## `aaaaRecords` (type: `string`):

IPv6 addresses

## `mxRecords` (type: `string`):

Mail servers

## `mailProvider` (type: `string`):

Detected mail provider

## `nsRecords` (type: `string`):

Nameservers

## `hasSpf` (type: `string`):

Has SPF record

## `hasDmarc` (type: `string`):

Has DMARC record

## `hasDkim` (type: `string`):

Has DKIM-related TXT

## `txtRecords` (type: `string`):

TXT records

## `registrar` (type: `string`):

Domain registrar

## `createdDate` (type: `string`):

Registration date

## `expiryDate` (type: `string`):

Expiry date

## `daysUntilExpiry` (type: `string`):

Days until expiry

## `dnssec` (type: `string`):

DNSSEC enabled

## `error` (type: `string`):

Error if failed

## `scrapedAt` (type: `string`):

Timestamp

# 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",
        "google.com",
        "cloudflare.com"
    ],
    "maxItems": 100,
    "maxConcurrency": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/bulk-dns-checker").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",
        "google.com",
        "cloudflare.com",
    ],
    "maxItems": 100,
    "maxConcurrency": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/bulk-dns-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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",
    "google.com",
    "cloudflare.com"
  ],
  "maxItems": 100,
  "maxConcurrency": 50
}' |
apify call haketa/bulk-dns-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=haketa/bulk-dns-checker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/dfxHExeATrTVFcsVd/builds/Mt3qiESZZpwpcWzB3/openapi.json
