DNS Propagation Checker avatar

DNS Propagation Checker

Pricing

$0.45 / 1,000 propagation checks

Go to Apify Store
DNS Propagation Checker

DNS Propagation Checker

Compare DNS answers for each domain and record type across 10 public resolvers. See propagation status, resolver coverage, answer values, response times, TTLs, and optional expected-value matches in your dataset. Use it to check DNS changes and investigate resolver differences.

Pricing

$0.45 / 1,000 propagation checks

Rating

0.0

(0)

Developer

Maxime Dupré

Maxime Dupré

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

🌐 Check DNS propagation with resolver evidence

DNS administrators, DevOps teams, and site owners can compare DNS answers for each domain and record type across 10 public DNS resolvers. The Actor saves propagation status, resolver coverage, answer values, response times, TTL and cache details when available, and optional expected-answer checks so you can review a DNS change in one run.

🧭 Use cases

📦 Returned data

The default dataset has one row for each submitted domain and selected record type. Each row keeps the answers and diagnostic details from the public resolvers, so you can see whether they agree. Add expected answers when you want each matching check to show a match, mismatch, or incomplete expected status. Turn on the run summary for grouped diagnostic details.

▶️ Running the Actor

  1. Add 1–200 domain names or hostnames.
  2. Choose one or more DNS record types. The same types are checked for every domain.
  3. Add expected answers when you want to compare selected resolver answers with values you provide.
  4. Set the resolver query timeout from 100 to 60,000 milliseconds, if needed.
  5. Run the Actor and open the default dataset. Turn on includeSummary when you also want the grouped run summary.

The prefilled input checks example.com for an A record with a 5,000-millisecond timeout. A DNS check can use the same settings or add more domains and record types.

🧾 Input

Provide the public input fields below. domains and recordTypes are required.

FieldTypeWhat it does
domainsarray of stringsRequired. Checks 1–200 domain names or hostnames. The same selected record types are used for every domain.
recordTypesarray of stringsRequired. Selects one or more DNS record types: A, AAAA, MX, CNAME, TXT, NS, SOA, PTR, or CAA.
expectedAnswersarray of objectsOptional. Compares resolver answers with expected values for selected domain and record-type pairs.
expectedAnswers[].domainstringRequired inside each expected answer. Names one of the submitted domains to compare.
expectedAnswers[].recordTypestringRequired inside each expected answer. Selects the DNS record type to compare.
expectedAnswers[].expectedValuesarray of stringsRequired inside each expected answer. Lists one or more DNS answer values to compare.
queryTimeoutMsintegerOptional; defaults to 5000. Sets the wait time for each public resolver query from 100 to 60000 milliseconds.
includeSummarybooleanOptional; defaults to false. When true, saves a run summary grouped by resolver disagreement, incomplete coverage, and expected-value mismatch.

This is the public input used by a successful current-beta default run:

{
"domains": [
"example.com"
],
"recordTypes": [
"A"
],
"queryTimeoutMs": 5000,
"includeSummary": false
}

📤 Output

The Actor returns links to its public output storages:

FieldTypeWhat it does
datasetstringOpens the default dataset with one row for each checked domain and DNS record type.
summarystringOpens the optional run summary with grouped resolver disagreement, incomplete coverage, and expected-value mismatch details.

Dataset row without expected answers

A standard DNS check row has the following fields. Nested fields use readable dotted paths.

FieldTypeWhat it does
domainstringDomain or hostname checked.
recordTypestringDNS record type checked.
propagationStatusstringShows consistent, inconsistent, or incomplete resolver agreement.
coverageStatusstringShows whether resolver coverage is complete or incomplete.
checkedAtdate-time stringTime when this check was completed.
resolverResultsarray of objectsAnswer and diagnostic details from each public DNS resolver.
resolverResults[].resolverNamestringName of the public DNS resolver.
resolverResults[].regionstringRegion reported for the resolver.
resolverResults[].responseTimeMsintegerResolver response time in milliseconds.
resolverResults[].statusstringResolver request status: answered, error, timeout, or noResponse.
resolverResults[].answersarray of stringsDNS answer values returned by the resolver. The array can be empty.
resolverResults[].ttlSecondsintegerTime to live for the returned DNS record, when available.
resolverResults[].cacheStatusstringCaching state for the returned DNS record, when available.
resolverResults[].errorMessagestringResolver error message when the request fails.

Genuine row from the successful current-beta default run:

{
"domain": "example.com",
"recordType": "A",
"propagationStatus": "consistent",
"coverageStatus": "complete",
"checkedAt": "2026-08-01T17:28:02.209Z",
"resolverResults": [
{
"resolverName": "Google Public DNS",
"region": "Global",
"responseTimeMs": 340,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 300
},
{
"resolverName": "Cloudflare 1.1.1.1",
"region": "Global",
"responseTimeMs": 280,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 190
},
{
"resolverName": "AdGuard DNS",
"region": "Global",
"responseTimeMs": 660,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 81
},
{
"resolverName": "OpenDNS",
"region": "North America",
"responseTimeMs": 470,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 147
},
{
"resolverName": "CleanBrowsing",
"region": "Global",
"responseTimeMs": 422,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 118
},
{
"resolverName": "DNS.SB",
"region": "Europe",
"responseTimeMs": 297,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 300
},
{
"resolverName": "LibreDNS",
"region": "Europe",
"responseTimeMs": 780,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 113
},
{
"resolverName": "ControlD Free DNS",
"region": "Global",
"responseTimeMs": 268,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 300
},
{
"resolverName": "NextDNS",
"region": "Global",
"responseTimeMs": 322,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 240
},
{
"resolverName": "FFMUC DNS",
"region": "Europe",
"responseTimeMs": 431,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 59
}
]
}

Dataset row with expected answers

When expectedAnswers is set for a domain and record type, the row also includes expectedValues and expectedStatus.

FieldTypeWhat it does
domainstringDomain or hostname checked.
recordTypestringDNS record type checked.
propagationStatusstringShows consistent, inconsistent, or incomplete resolver agreement.
coverageStatusstringShows whether resolver coverage is complete or incomplete.
expectedValuesarray of stringsValues supplied for the expected-answer comparison.
expectedStatusstringShows match, mismatch, or incomplete for the expected-answer comparison.
checkedAtdate-time stringTime when this check was completed.
resolverResultsarray of objectsAnswer and diagnostic details from each public DNS resolver.
resolverResults[].resolverNamestringName of the public DNS resolver.
resolverResults[].regionstringRegion reported for the resolver.
resolverResults[].responseTimeMsintegerResolver response time in milliseconds.
resolverResults[].statusstringResolver request status: answered, error, timeout, or noResponse.
resolverResults[].answersarray of stringsDNS answer values returned by the resolver.
resolverResults[].ttlSecondsintegerTime to live for the returned DNS record, when available.
resolverResults[].cacheStatusstringCaching state for the returned DNS record, when available.
resolverResults[].errorMessagestringResolver error message when the request fails.

Genuine row from a successful current-beta run with expected answers:

{
"domain": "example.com",
"recordType": "A",
"propagationStatus": "consistent",
"coverageStatus": "complete",
"checkedAt": "2026-08-01T17:30:47.234Z",
"resolverResults": [
{
"resolverName": "Google Public DNS",
"region": "Global",
"responseTimeMs": 143,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 300
},
{
"resolverName": "Cloudflare 1.1.1.1",
"region": "Global",
"responseTimeMs": 284,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 102
},
{
"resolverName": "AdGuard DNS",
"region": "Global",
"responseTimeMs": 193,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 130
},
{
"resolverName": "OpenDNS",
"region": "North America",
"responseTimeMs": 183,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 176
},
{
"resolverName": "CleanBrowsing",
"region": "Global",
"responseTimeMs": 222,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 268
},
{
"resolverName": "DNS.SB",
"region": "Europe",
"responseTimeMs": 423,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 135
},
{
"resolverName": "LibreDNS",
"region": "Europe",
"responseTimeMs": 632,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 278
},
{
"resolverName": "ControlD Free DNS",
"region": "Global",
"responseTimeMs": 356,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 256
},
{
"resolverName": "NextDNS",
"region": "Global",
"responseTimeMs": 253,
"status": "answered",
"answers": [
"104.20.23.154",
"172.66.147.243"
],
"ttlSeconds": 182
},
{
"resolverName": "FFMUC DNS",
"region": "Europe",
"responseTimeMs": 606,
"status": "answered",
"answers": [
"172.66.147.243",
"104.20.23.154"
],
"ttlSeconds": 198
}
],
"expectedValues": [
"104.20.23.154",
"172.66.147.243"
],
"expectedStatus": "match"
}

💳 Pricing

The Actor charges $0.00045 for each successful propagation check for one submitted domain and DNS record type. A run can create one charged event for each successful domain-and-record-type check.

🔌 Integrations

Use the Apify API to start runs and read the default dataset or optional run summary. The structured dataset can feed your own DNS change checks or monitoring workflow.

❓ FAQ

What does consistent mean?

consistent means the answers returned by the queried public resolvers agree for that domain and record type. inconsistent means they differ; incomplete means there were not enough answers to make a full comparison.

Can this prove propagation everywhere?

No. It reports observations from 10 selected public resolvers, not a full geographic census of end users.

What happens when a resolver errors or times out?

The resolver result keeps a status such as error, timeout, or noResponse. coverageStatus can show incomplete coverage, and includeSummary can group incomplete responses.

Can I compare answers with expected values?

Yes. Add an object in expectedAnswers for a submitted domain and record type, then add one or more expectedValues. The row reports match, mismatch, or incomplete.

Can I check private DNS or DNSSEC?

No. The Actor queries selected public resolvers and does not validate DNSSEC chains.

Does it change my DNS records?

No. It reads answers and reports comparisons; it does not modify DNS records or deploy changes.

How many rows does a run save?

It saves one row for each submitted domain and selected record-type combination. The same selected record types are checked for every submitted domain.

What does queryTimeoutMs control?

It sets how long each public resolver query may wait, from 100 to 60,000 milliseconds. It does not change which domains or record types are checked.

📝 Changelog

🆕 0.0: Initial release

  • Compare DNS answers for selected domains and record types across 10 public resolvers, with propagation status, resolver coverage, answer values, response times, TTLs, optional expected-answer checks, and an optional run summary.

🆘 Support

For issues, questions, or feature requests, file a ticket and I'll fix or implement it in less than 24h 🫡

Made with ❤️ by Maxime Dupré