DNS Record Lookup — A, MX, TXT, NS, CNAME, SOA API avatar

DNS Record Lookup — A, MX, TXT, NS, CNAME, SOA API

Pricing

from $2.40 / 1,000 successful lookups

Go to Apify Store
DNS Record Lookup — A, MX, TXT, NS, CNAME, SOA API

DNS Record Lookup — A, MX, TXT, NS, CNAME, SOA API

Look up DNS records for any domain — A, AAAA, MX, TXT, NS, CNAME, or SOA — straight from Cloudflare's public DNS-over-HTTPS resolver, with DNSSEC validation status per record. Paste domains, press Start. Charged once per domain that resolves — NXDOMAIN and empty responses cost nothing.

Pricing

from $2.40 / 1,000 successful lookups

Rating

0.0

(0)

Developer

Adrian Voss

Adrian Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

DNS Record Lookup

You give this actor a list of domains, and it queries their live DNS records — A, AAAA, MX, TXT, NS, CNAME, or SOA — straight from Cloudflare's public DNS-over-HTTPS resolver, the same infrastructure behind 1.1.1.1. No API key, no scraping, no zone transfer — just the answer a DNS resolver already gives out publicly, returned as one flat row per domain (or one row per record, if you want it that way).

Who it's for

The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and per-domain: a few tenths of a cent for a row that was actually found, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists — VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No seat licence, no monthly minimum, no credit system to decode.

For DNS specifically, that means you paste a list of domains and get back what each one's nameservers are actually publishing right now — mail routing, IP addresses, TXT-record policy, DNSSEC status — without opening a terminal or writing a resolver loop yourself.

Why this one

  • Queries a real resolver, not a scrape. Every lookup goes to Cloudflare's public DNS-over-HTTPS endpoint over HTTPS — the same service that answers 1.1.1.1 — so there's nothing brittle to break when a target site changes its HTML.
  • All seven record types from one actor. A, AAAA, MX, TXT, NS, CNAME, SOA — pick per domain by appending :TYPE to the input, instead of running seven separate tools.
  • DNSSEC and recursion signal on every row. dnssecValidated and recursionAvailable come back with every lookup, useful for a security posture pass across a domain list without a separate DNSSEC checker.
  • Misses are free. NXDOMAIN, SERVFAIL, and a NOERROR response with zero answer records are all classified as not-found and never billed — you only pay for a domain that actually resolved.
  • Row shape you choose. expandRows gives you one row per DNS record (handy for a spreadsheet or a Clay table) or one row per domain with all its records nested in an array — either way, you're billed once per domain, not per record.

What you get

Every row carries these fields. domain through dnssecValidated are the DNS-specific fields (pulled straight from .actor/profile.json); the rest are the same envelope every actor in this catalogue uses.

FieldTypeDescription
querystringThe input exactly as given — example.com or example.com:MX
foundbooleantrue if the domain resolved for the queried type with at least one answer record
statusstring"OK" on a found row; NOT_FOUND, BLOCKED, REQUEST_FAILED, or BAD_FORMAT on a miss
domainstringThe queried domain, lowercased
queriedTypestringThe DNS record type that was queried: A, AAAA, MX, TXT, NS, CNAME, or SOA
recordsarrayEvery answer record Cloudflare returned for that type — name, type (numeric DNS type), ttl, and data per record
recursionAvailablebooleanThe resolver's RA flag — whether recursive lookups were available for this query
dnssecValidatedbooleanThe resolver's AD (Authenticated Data) flag — true only when the response chain was cryptographically validated
scrapedAtstring (ISO 8601)Timestamp of the lookup
messagestringPresent only on miss rows — a human-readable reason (e.g. why the domain didn't resolve)

With expandRows on (the default), each record in records becomes its own dataset row instead of a nested array — same fields, one DNS record per row. If any data field name were to collide with a reserved envelope key (query, found, status, message, scrapedAt), it would be renamed to <key>Value in the output — that doesn't happen with this actor's current fields, but it's the rule the shared harness applies across the whole catalogue so column names never silently overwrite each other.

Price

$4 per 1,000 domains, plus a $0.005 start fee. Misses (found:false) are never charged.

That's $0.004 per resolved domain at the FREE tier, dropping to $0.0024 per resolved domain on paid tiers — the $0.005 actor-start charge is fixed regardless of tier. 1,000 domains through this actor: ~$4 if every one resolves, less for any that come back NXDOMAIN or SERVFAIL. The same 1,000 rows through a credit-based enrichment platform: $80–$400. A domain that doesn't resolve for the queried type costs you nothing either way — you still get a row (found: false), you just aren't billed for it.

How to use

  1. In the Apify Console. Open the actor page and click Start — the domains field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. Via the API. Call it directly with a POST request — no Console needed once you have an API token:
    curl "https://api.apify.com/v2/acts/accountable_eel~dns-record-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"domains":["github.com"]}'
  3. On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
  1. Paste a list of domains into the input, one per line. github.com on its own queries the A record by default.
  2. To query a different record type, append :TYPEgithub.com:MX, cloudflare.com:TXT, example.com:SOA. Want two types for the same domain? List it twice, once per type — each is billed independently.
  3. Turn on Try it first (testRun) to run just the first 5 items and check the shape of the output before committing to a full list.
  4. Turn on Hide rows with no result (onlyFound) if you only want rows that actually resolved in your dataset — misses are free either way, this just keeps them out of the export.
  5. Leave maxConcurrency at its default of 5 unless you have a reason to push it — this target has no browser fallback, so a burst of parallel requests risks getting rate-limited rather than finishing faster.
  6. Run it, then export the dataset as CSV/JSON or pull it via the API into whatever pulls your enrichment data — Clay, n8n, a script, or an agent.

Input

{
"domains": [
"github.com"
]
}

One domain per line. Defaults to an A record lookup; append :TYPE (A, AAAA, MX, TXT, NS, CNAME, or SOA) to query a different record type, e.g. github.com:MX. Accepted formats: github.com, github.com:MX.

{
"items": ["github.com", "github.com:MX", "cloudflare.com:TXT"],
"maxConcurrency": 5
}

items is a list of domains to query. By default each domain is queried for its A record; append :TYPE (one of A, AAAA, MX, TXT, NS, CNAME, SOA) to query a different record type, e.g. github.com:MX. One dataset row is returned per item; rows with "found": false are never charged. maxConcurrency controls how many DNS queries run in parallel — this target has no browser fallback, so keeping it conservative avoids getting rate-limited.

Sample output

queryfoundstatusdomainqueriedTyperecordsrecursionAvailablednssecValidatedscrapedAt
github.comtrueOKgithub.comAtruefalse2026-08-24T06:01:23.530Z

One row per item, for example:

{
"query": "github.com:MX",
"found": true,
"data": {
"domain": "github.com",
"queriedType": "MX",
"records": [
{ "name": "github.com", "type": 15, "ttl": 3600, "data": "1 aspmx.l.google.com." }
],
"recursionAvailable": true,
"dnssecValidated": false
},
"scrapedAt": "2026-08-21T10:00:00.000Z"
}

Domains that don't resolve for the queried type — NXDOMAIN, SERVFAIL, or a NOERROR response with no answer records — still get a row ("found": false), so you always get one row per input, but you're never charged for those.

Use it from Clay, n8n, Make, or an AI agent

This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.

curl "https://api.apify.com/v2/acts/accountable_eel~dns-record-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
-X POST \
-H "Content-Type: application/json" \
-d '{"domains":["github.com"]}'

n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~dns-record-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"domains":["github.com"]} (swap in an expression from an earlier node for a real value).

Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~dns-record-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"domains":["{{domain}}"]}, mapping the row's domain into the domains array.

MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "DNS Record Lookup | Apify" — the agent will find and run this actor.

Tips

  • Query more than one record type for the same domain by listing it twiceexample.com:A and example.com:MX as separate input items. Each is billed independently as its own lookup, so you only pay for the types you actually ask for.
  • dnssecValidated: false doesn't mean "no DNSSEC." It reflects Cloudflare's AD flag for that one query — true only when the resolver could cryptographically validate the response chain. A false can mean DNSSEC isn't configured, or just that validation wasn't attempted for that lookup. If you need a definitive DNSSEC posture, cross-check a false against the domain's DNSKEY/DS records directly.
  • Turn expandRows off if you want one row per domain. With multiple MX or TXT records, the default (on) gives you one row per record — cleaner for filtering, but it multiplies row count on domains with a lot of records (still billed once per domain either way).
  • Keep maxConcurrency at 5 for large batches. This target has no browser fallback to fall back on if Cloudflare starts throttling you, so slow-and-steady finishes a 10,000-domain list more reliably than a burst that gets rate-limited partway through.
  • Use MX and TXT together for a quick deliverability read before a cold outreach or domain migration — MX tells you where mail routes, TXT surfaces SPF/DMARC records (look for v=spf1 or v=DMARC1 in the data field).
  • Resolve A/AAAA/CNAME across a domain list for infrastructure discovery — the IP or CNAME target tells you which host, CDN, or cloud provider a domain points to, without visiting the site.
  • Check NS and SOA after a DNS cutover to confirm propagation finished — query the same domain before and after a migration and diff the records array.
  • Run dnssecValidated across a portfolio you manage as a lightweight security-posture pass — it won't replace a dedicated DNSSEC audit, but it flags which domains are worth a closer look.

vs. alternatives

What it costsWhat you getTrade-off
This actor (dns-record-lookup)$0.004 per resolved domain (FREE tier, down to $0.0024 on paid tiers), $0.005 actor start, nothing for NXDOMAIN/SERVFAILOne row per domain or per record — A/AAAA/MX/TXT/NS/CNAME/SOA, plus DNSSEC and recursion flags, from one API callOne resolver (Cloudflare's), one record type per query item — no zone transfer, no historical record archive
DIY (whois/dig)Free, your timeThe same records, one domain at a time from a terminalFine for a handful of domains; across a list of thousands you're writing your own retry logic, rate limiting, and parsing to get a flat table out of it
Clay$0.08–$0.40 per enriched row in credits, on top of a seatA whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around itIf you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step.

Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.

FAQ

What happens if a domain doesn't resolve — do I still pay? No. NXDOMAIN, SERVFAIL, and a NOERROR response with zero answer records for the queried type are all treated as a miss (found: false, with a status of NOT_FOUND, BLOCKED, REQUEST_FAILED, or BAD_FORMAT). Misses still produce a dataset row so your row count matches your input count, but they're never billed.

Do I need a Cloudflare API key? No. Cloudflare's DNS-over-HTTPS resolver is free and public — this actor calls it directly, with no credentials required on your end.

Are there rate limits I should worry about on a large batch? maxConcurrency (default 5) controls how many DNS queries run in parallel. This target has no browser fallback, so keep it conservative on large runs — a burst of parallel requests risks getting throttled rather than finishing faster. A list of a few thousand domains at the default concurrency runs without issue.

How fresh is the data — could I get a stale record? Every run queries Cloudflare's resolver live, so you get whatever it's currently serving. That said, DNS itself is cached: Cloudflare's resolver respects each record's TTL, so a record that changed in the last few minutes (or hours, for a long-TTL SOA or NS record) may not have propagated to the resolver yet. This actor reports what the resolver has right now, not a guaranteed real-time read of the authoritative nameserver.

Do I need to configure a proxy? No. Requests go to Cloudflare's public resolver, not to the target company's own infrastructure, so there's nothing to spoof or rotate around. The proxy configuration field is there because the shared actor template includes it, but DNS-over-HTTPS to Cloudflare doesn't need one.

Is DNS record data personal data under GDPR? DNS records describe a domain's infrastructure — IP addresses, mail servers, nameservers, TXT policy strings — not people. They're not personal data, and this actor doesn't process, store, or return anything about individuals.

Can I schedule this to run on a cadence? Yes, through Apify's own Scheduler — set up a recurring run against a saved input (e.g. a maintained list of domains you monitor) and it queries fresh on each run. There's no built-in delta/diff feature here — every run is a full lookup against the current input list, so if you want to know what changed between runs, keep the previous dataset export and diff it yourself against the new one, or expand TXT/MX/NS and compare the record values.

Can an AI agent call this directly? Yes. It's registered on the Apify MCP server — a client like Claude or Cursor can find and run it by name ("DNS Record Lookup | Apify") — or call the Apify API directly over HTTP, same as the curl example above.

  • Domain RDAP Lookup — registration data (registrar, creation/expiry dates, nameservers) for the same domain list, from RDAP instead of DNS.
  • Email Deliverability Check — mail route, disposable/role detection, and provider fingerprint for a domain, building on the same MX/TXT signal this actor surfaces raw.
  • Tech Stack Lookup — what a domain is actually running (CMS, analytics, ecommerce platform), for when DNS tells you where it points but not what's there.