# DNS Records Lookup: A, MX, TXT, NS and More | $1/1K (`one_dollar_store/dns-records-lookup`) Actor

$1 per 1,000 results, platform usage included. DNS records for a list of domains: A, AAAA, MX, TXT, NS, CNAME, SOA and CAA, with TTLs, plus optional SPF and DMARC checks. Read over public DNS over HTTPS. No API key.

- **URL**: https://apify.com/one_dollar_store/dns-records-lookup.md
- **Developed by:** [One Dollar Store](https://apify.com/one_dollar_store) (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

from $1.00 / 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.

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: A, AAAA, MX, TXT, NS, CNAME, SOA and CAA for a List of Domains

**$1 per 1,000 domains looked up. Platform usage included. No rental, no minimum.**

Give it a list of domains and it returns their DNS records: IPv4 and IPv6 addresses, mail servers, TXT records, name servers, aliases, the zone start of authority and the certificate authorities allowed by CAA. Each record type comes with its TTL. Optional SPF and DMARC checks. No account with a DNS provider and no API key.

[Open it in Apify Console](https://console.apify.com/actors/p1rL7Krcxp52xUG5M/input)

### What it costs

| Domains | This actor |
|---|---|
| 1,000 | $1.00 |
| 10,000 | $10.00 |
| 100,000 | $100.00 |

Plus $0.001 per run. One flat price, platform usage included, so there is no separate compute or proxy bill. One domain is one result, however many record types you ask for. A weekly check of 500 domains costs about $0.50 a run, or about $2 a month. A domain that does not exist is returned as a row with status `NXDOMAIN` and charged like any other row. A lookup that fails on both resolvers returns no row and is not charged.

### Why use it

- **One row per domain.** All record types sit in one row, so 8 record types for 1,000 domains is 1,000 results, not 8,000.
- **Two public resolvers.** Queries go to Cloudflare over DNS over HTTPS. If it fails or answers SERVFAIL, Google Public DNS is asked instead.
- **Mail checks built in.** Turn on SPF and DMARC and each row gets the SPF record, the DMARC record and the DMARC policy.
- **Flat output when you want it.** Switch on one row per record and every record becomes its own line with domain, type, value and TTL.

### Quick start

1. Open the actor, paste your domains, press **Start**.
2. Or paste this input:

```json
{ "domains": ["apify.com", "wikipedia.org"], "recordTypes": ["A", "MX", "TXT", "NS"], "emailAuth": true }
```

3. Download the results as JSON, CSV or Excel, or read them through the API.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/one_dollar_store~dns-records-lookup/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"domains": ["apify.com", "wikipedia.org"], "recordTypes": ["A", "MX", "NS"]}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("one_dollar_store/dns-records-lookup").call(
    run_input={"domains": ["apify.com", "wikipedia.org"], "recordTypes": ["A", "MX", "NS"]}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["domain"], item.get("a"), item.get("ns"))
```

### Use it from an AI assistant

Claude, ChatGPT, Cursor and other assistants can call this actor through Apify's MCP server. Add it with this server address:

```
https://mcp.apify.com?tools=one_dollar_store/dns-records-lookup
```

Then ask, for example: "Look up the MX and TXT records for apify.com and tell me whether it has an SPF and DMARC policy."

### Switching from another DNS lookup actor

Domains go in `domains` (a list). Links, host names with a port and email addresses are accepted; the host name is taken from them. Choose records with `recordTypes`. The core output fields are `domain`, `a`, `aaaa`, `mx`, `txt`, `ns`, `cname`, `soa` and `caa`. If you need one line per record, set `rowPerRecord` to true and read `domain`, `type`, `value` and `ttl`.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `domains` | list of text | required | Domains or host names, for example `example.com` or `mail.example.com`. Repeats are removed. |
| `recordTypes` | list | all eight | Any of `A`, `AAAA`, `MX`, `TXT`, `NS`, `CNAME`, `SOA`, `CAA`. |
| `emailAuth` | true or false | false | Adds `spf`, `dmarc`, `dmarcPolicy` and `dmarcSubdomainPolicy` to each row. One more lookup per domain, no extra row. Not used with `rowPerRecord`. |
| `rowPerRecord` | true or false | false | One row per record instead of one row per domain. Every row is charged. |
| `resolver` | text | `cloudflare` | `cloudflare` or `google`. The other one is the back up. |
| `maxItems` | number | 1000 | Most rows in the run. Minimum 10. |

### Output fields

One row per domain (default):

| Field | Meaning |
|---|---|
| `domain` | The host name that was looked up, in lower case. |
| `status` | `NOERROR` (the name exists) or `NXDOMAIN` (it does not). |
| `a`, `aaaa` | IPv4 and IPv6 addresses. |
| `mx` | Mail servers as `{priority, host}`, lowest priority first. |
| `txt` | TXT records. Strings split by DNS are joined. |
| `ns` | Name servers. |
| `cname` | The alias target, when the name is an alias. Left out otherwise. |
| `soa` | `primaryNs`, `adminEmail`, `serial`, `refresh`, `retry`, `expire`, `minimumTtl`. |
| `caa` | Certificate authority rules as `{flags, tag, value}`. |
| `ttl` | The lowest TTL in seconds for each record type, for example `{"a": 300}`. |
| `spf`, `dmarc`, `dmarcPolicy`, `dmarcSubdomainPolicy` | Only with `emailAuth`, and only when the record exists. |
| `failedTypes` | Record types that could not be read on either resolver. Rare. |
| `resolver`, `queriedAt` | Which service answered and when. |

A type with no records comes back as an empty list. With `rowPerRecord` the fields are `domain`, `type`, `value`, `ttl`, plus `priority` (MX), `caaFlags` and `caaTag` (CAA) and `soa` (SOA), with `resolver` and `queriedAt`.

### Sample results

Real rows from test runs on 9 October 2026 (long TXT lists and some address lists shortened).

```json
[
  {"domain": "wikipedia.org", "status": "NOERROR", "a": ["208.80.154.224"], "aaaa": ["2620:0:861:ed1a::1"], "mx": [{"priority": 10, "host": "mx-in1001.wikimedia.org"}, {"priority": 10, "host": "mx-in2001.wikimedia.org"}], "txt": ["v=spf1 include:_cidrs.wikimedia.org ~all", "... 2 more"], "ns": ["ns0.wikimedia.org", "ns1.wikimedia.org", "ns2.wikimedia.org"], "soa": {"primaryNs": "ns0.wikimedia.org", "adminEmail": "hostmaster@wikimedia.org", "serial": 2026060420, "refresh": 43200, "retry": 7200, "expire": 1209600, "minimumTtl": 3600}, "caa": [{"flags": 0, "tag": "iodef", "value": "mailto:dns-admin@wikimedia.org"}, {"flags": 0, "tag": "issue", "value": "letsencrypt.org"}, {"flags": 0, "tag": "issue", "value": "pki.goog"}], "ttl": {"a": 87, "aaaa": 73, "mx": 300, "txt": 600, "ns": 166257, "soa": 3600, "caa": 600}, "resolver": "cloudflare", "queriedAt": "2026-10-08T22:57:19.375Z"},
  {"domain": "python.org", "status": "NOERROR", "a": ["151.101.128.223", "151.101.0.223"], "aaaa": ["2a04:4e42:600::223", "2a04:4e42::223"], "mx": [{"priority": 50, "host": "mail.python.org"}], "txt": ["v=spf1 mx ip4:188.166.95.178/32 ip6:2a03:b0c0:2:d0::71:1 include:stspg-customer.com include:_spf.google.com include:mailgun.org ~all", "... 12 more"], "ns": ["ns-1134.awsdns-13.org", "ns-2046.awsdns-63.co.uk", "ns-484.awsdns-60.com", "ns-981.awsdns-58.net"], "soa": {"primaryNs": "ns-2046.awsdns-63.co.uk", "adminEmail": "awsdns-hostmaster@amazon.com", "serial": 1, "refresh": 7200, "retry": 900, "expire": 1209600, "minimumTtl": 86400}, "caa": [], "ttl": {"a": 300, "aaaa": 218, "mx": 60, "txt": 300, "ns": 86400, "soa": 900}, "resolver": "cloudflare", "queriedAt": "2026-10-08T22:57:19.478Z"},
  {"domain": "nodejs.org", "status": "NOERROR", "a": ["104.16.213.131", "104.16.212.131"], "aaaa": ["2606:4700::6810:d483", "2606:4700::6810:d583"], "mx": [{"priority": 10, "host": "aspmx.l.google.com"}, {"priority": 20, "host": "alt1.aspmx.l.google.com"}, {"priority": 20, "host": "alt2.aspmx.l.google.com"}, {"priority": 30, "host": "aspmx2.googlemail.com"}, {"priority": 30, "host": "aspmx3.googlemail.com"}], "txt": ["google-site-verification=v0MKccGKHVIlJbu0s9K45qnPGB7EBWnKzjpsd010r4E", "v=spf1 include:aspmx.googlemail.com -all"], "ns": ["meera.ns.cloudflare.com", "pablo.ns.cloudflare.com"], "soa": {"primaryNs": "meera.ns.cloudflare.com", "adminEmail": "dns@cloudflare.com", "serial": 2414071662, "refresh": 10000, "retry": 2400, "expire": 604800, "minimumTtl": 1800}, "caa": [], "ttl": {"a": 238, "aaaa": 113, "mx": 300, "txt": 300, "ns": 86400, "soa": 1800}, "resolver": "cloudflare", "queriedAt": "2026-10-08T22:57:19.521Z"}
]
```

### Limits

- **DNS over HTTPS only.** Answers come from Cloudflare (1.1.1.1) or Google Public DNS, so they are what a public resolver returns, including cached answers. TTLs are the remaining time on the resolver, so the same record can show different TTLs in two runs.
- **No zone transfers and no record guessing.** Only the record types listed above are read. The actor cannot list every subdomain of a domain; use the Subdomain Finder for that.
- **DNSSEC records are not returned.** There is no DS, DNSKEY or RRSIG output.
- **Names only.** IP addresses are skipped, so there are no reverse (PTR) lookups.
- **Failed lookups are not returned.** If neither resolver answers (timeout, SERVFAIL on both), the domain is listed in the run summary under `failedDomains` and no row is charged. A domain that does not exist is returned with status `NXDOMAIN`.
- **Public side only.** Some domains answer differently by location, and split DNS zones are seen as the public sees them.

### FAQ

**How much does it cost to look up 10,000 domains?**
$10, plus $0.001 for each run. That is for one row per domain. With `rowPerRecord` on, each record is a row and costs $0.001.

**Do I pay for compute or proxy on top?**
No. Platform usage is included in the $1 per 1,000 price.

**Do I need an API key or a DNS account?**
No. The actor asks two public DNS over HTTPS services. There is nothing to sign up for.

**Can it check email setup for many domains?**
Yes. Turn on `emailAuth` to get the SPF record, the DMARC record and the DMARC policy for each domain, next to the MX records.

**Why is a record type an empty list?**
The domain has no record of that type. An empty `mx` list usually means the domain does not receive email, or that the name is an alias with no mail setup of its own.

**Is it legal?**
The actor sends standard DNS queries and returns records that DNS publishes for anyone to read. How you use the data is your responsibility: follow the law where you live and the terms of the resolver services (Cloudflare and Google Public DNS).

**Is this an official Cloudflare or Google product?**
No. It is an independent tool and is not affiliated with or endorsed by Cloudflare or Google.

**Do I need an Apify account?**
Yes. Actors run from an Apify account, and a free account is enough to start: it includes $5 of platform usage every month. You can [sign up here](https://www.apify.com?fpr=ymnoit). This is a referral link and it costs you nothing.

**Is there a limit on the free plan?**
Yes. A run started from a free plan account delivers the first 10 results, then ends with a message and a link to the plans. Any paid plan returns everything you ask for, up to your own limit. The price per result is the same on every plan.

### More from The One Dollar Store

Every actor here costs $1 per 1,000 results, platform usage included. See the whole store: https://apify.com/one_dollar_store

**Domains and apps**

- [Apple App Store Scraper](https://apify.com/one_dollar_store/app-store-apps-scraper): App details, ratings and search results.
- [Domain WHOIS Lookup](https://apify.com/one_dollar_store/domain-whois-rdap-lookup): Registrar, dates and name servers for any domain.
- [Subdomain Finder](https://apify.com/one_dollar_store/subdomain-finder-crtsh): Subdomains found in certificate logs.
- [Shopify App Store Scraper](https://apify.com/one_dollar_store/shopify-app-store-scraper): Shopify apps with ratings and pricing.
- [Hugging Face Scraper](https://apify.com/one_dollar_store/hugging-face-models-scraper): Models and datasets with downloads and tags.

### Changelog

- October 2026: first release.

# Actor input Schema

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

Domain or host names to look up, one per line, for example example.com or mail.example.com. Links and email addresses are accepted too: the host name is taken from them. Names with accents are converted to the xn-- form.

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

Which records to read for every domain. Leave all eight selected for a full picture.

## `emailAuth` (type: `boolean`):

Adds the SPF record (from the TXT records) and the DMARC record (read from \_dmarc.<domain>) to each row, with the DMARC policy. Costs one more lookup per domain, not one more row.

## `rowPerRecord` (type: `boolean`):

Off: one row per domain with all its records. On: one flat row for every record (domain, type, value, TTL), which is easier to load into a table. Each row is charged.

## `resolver` (type: `string`):

Public DNS over HTTPS service that answers the queries. If it fails, the other one is tried.

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

The run stops after this many rows. Minimum 10.

## Actor input object example

```json
{
  "domains": [
    "apify.com",
    "wikipedia.org",
    "github.com",
    "python.org",
    "nodejs.org"
  ],
  "recordTypes": [
    "A",
    "AAAA",
    "MX",
    "TXT",
    "NS",
    "CNAME",
    "SOA",
    "CAA"
  ],
  "emailAuth": false,
  "rowPerRecord": false,
  "resolver": "cloudflare",
  "maxItems": 100
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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": [
        "apify.com",
        "wikipedia.org",
        "github.com",
        "python.org",
        "nodejs.org"
    ],
    "recordTypes": [
        "A",
        "AAAA",
        "MX",
        "TXT",
        "NS",
        "CNAME",
        "SOA",
        "CAA"
    ],
    "emailAuth": false,
    "rowPerRecord": false,
    "resolver": "cloudflare",
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("one_dollar_store/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": [
        "apify.com",
        "wikipedia.org",
        "github.com",
        "python.org",
        "nodejs.org",
    ],
    "recordTypes": [
        "A",
        "AAAA",
        "MX",
        "TXT",
        "NS",
        "CNAME",
        "SOA",
        "CAA",
    ],
    "emailAuth": False,
    "rowPerRecord": False,
    "resolver": "cloudflare",
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("one_dollar_store/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": [
    "apify.com",
    "wikipedia.org",
    "github.com",
    "python.org",
    "nodejs.org"
  ],
  "recordTypes": [
    "A",
    "AAAA",
    "MX",
    "TXT",
    "NS",
    "CNAME",
    "SOA",
    "CAA"
  ],
  "emailAuth": false,
  "rowPerRecord": false,
  "resolver": "cloudflare",
  "maxItems": 100
}' |
apify call one_dollar_store/dns-records-lookup --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,one_dollar_store/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/p1rL7Krcxp52xUG5M/builds/ywkqSivcBNx52oHpL/openapi.json
