
How to check DNS propagation worldwide?
To check DNS propagation worldwide, first confirm that your domain's authoritative nameservers are serving the new record, then query a spread of public resolvers in different regions and compare their answers. The easiest way is an online propagation checker such as whatsmydns.net or dnschecker.org, which query dozens of resolvers around the world at once. For more control, use dig against the authoritative servers and the big public resolvers, check the remaining TTL on each cached answer, and query DNS over HTTPS endpoints from a script.
"Propagation" is really just caches expiring at different times, so checking it is about finding out which caches still hold the old answer and for how long. This guide shows you how to verify the source first, which tools to use for a quick global view, how to check from the command line, how to tell how long the remaining resolvers will take, and the special case of nameserver changes, which work differently from ordinary record changes.
What You're Actually Checking
When you change a record, the authoritative nameservers start serving the new value almost immediately. Resolvers around the world that already cached the old value keep serving it until its TTL runs out. A resolver that hasn't cached the record fetches the new one straight away.
So a propagation check answers three questions:
- Is the new value live at the source? If not, nothing else matters yet.
- Which resolvers still have the old value?
- How long until they expire it?
It's worth checking all three in that order.
Step 1: Verify the Authoritative Nameservers
Always start at the source. Find your domain's nameservers:
dig example.com NS +short
ns1.example.net.
ns2.example.net.
Then ask each one directly, with recursion turned off so you see exactly what that server holds:
dig @ns1.example.net www.example.com A +norecurse +noall +answer
dig @ns2.example.net www.example.com A +norecurse +noall +answer
www.example.com. 300 IN A 198.51.100.20
www.example.com. 300 IN A 198.51.100.20
Both servers should return the new value. If one of them still shows the old value, your provider hasn't finished updating all its servers, or you're running your own secondary servers that haven't pulled the change. Compare the SOA serial on each:
for ns in $(dig +short example.com NS); do
echo -n "$ns "
dig @"$ns" example.com SOA +short | awk '{print $3}'
done
ns1.example.net. 2026101703
ns2.example.net. 2026101702
Here ns2 is one version behind. For a self-hosted secondary, check that zone transfers or NOTIFY messages are working. For a managed provider, this usually catches up within a minute or two.
Step 2: Use an Online Propagation Checker
Online checkers query resolvers in many countries at the same time and show the results on a map. They're the fastest way to get a global picture without any setup.
Popular options include:
- whatsmydns.net: Shows results for many record types from servers across the world.
- dnschecker.org: Similar global view, plus other DNS and network tools.
To use one:
- Enter the full hostname, such as
www.example.com, not just the domain. - Choose the record type you changed (A, AAAA, CNAME, MX, TXT, NS and so on).
- Look for locations that return the old value or no value.
Keep in mind what these tools can and can't tell you:
- They test a sample of resolvers, not all of them: Your visitors' ISPs may not be in the list.
- Results can vary between refreshes: Large public resolvers run many independent caches behind one address, so two queries a second apart can hit different caches.
- Some locations may use location-aware answers: If your DNS provider returns different IPs depending on the resolver's location, different answers in different countries are expected, not a propagation problem.
Step 3: Query Public Resolvers from the Command Line
You can check the major public resolvers yourself with dig. The +noall +answer options trim the output to just the answer, which includes the remaining TTL:
dig @1.1.1.1 www.example.com A +noall +answer
dig @8.8.8.8 www.example.com A +noall +answer
dig @9.9.9.9 www.example.com A +noall +answer
dig @208.67.222.222 www.example.com A +noall +answer
www.example.com. 300 IN A 198.51.100.20
www.example.com. 2650 IN A 192.0.2.10
www.example.com. 241 IN A 198.51.100.20
www.example.com. 300 IN A 198.51.100.20
In this example, Google Public DNS (8.8.8.8) still has the old address 192.0.2.10, with 2,650 seconds left on the cache. It will switch to the new value in about 44 minutes.
On Windows without dig, PowerShell's Resolve-DnsName does the same job and also shows the TTL:
"1.1.1.1","8.8.8.8","9.9.9.9","208.67.222.222" | ForEach-Object {
$r = Resolve-DnsName www.example.com -Type A -Server $_ -DnsOnly |
Where-Object Section -eq "Answer"
[pscustomobject]@{ Resolver = $_; Address = $r.IPAddress; TTL = $r.TTL }
}
A Reusable Bash Script
This script checks a list of resolvers and flags any that don't return the value you expect:
#!/usr/bin/env bash
# Usage: ./propcheck.sh www.example.com A 198.51.100.20
name="$1"; type="$2"; expected="$3"
resolvers=(
"1.1.1.1 Cloudflare"
"8.8.8.8 Google"
"9.9.9.9 Quad9"
"208.67.222.222 OpenDNS"
"94.140.14.14 AdGuard"
)
for entry in "${resolvers[@]}"; do
ip="${entry%% *}"; label="${entry#* }"
answer=$(dig @"$ip" "$name" "$type" +noall +answer +time=3 +tries=1 2>/dev/null |
awk -v t="$type" '$4==t')
value=$(echo "$answer" | awk '{$1=$2=$3=$4=""; sub(/^ +/, ""); print}' | sort | paste -sd, -)
ttl=$(echo "$answer" | awk 'NR==1{print $2}')
if [[ "$value" == *"$expected"* ]]; then status="OK"; else status="OLD"; fi
printf "%-8s %-11s %-16s ttl=%-6s %s\n" "$status" "$label" "$ip" "${ttl:--}" "${value:-no answer}"
done
OK Cloudflare 1.1.1.1 ttl=300 198.51.100.20
OLD Google 8.8.8.8 ttl=2650 192.0.2.10
OK Quad9 9.9.9.9 ttl=241 198.51.100.20
OK OpenDNS 208.67.222.222 ttl=300 198.51.100.20
OK AdGuard 94.140.14.14 ttl=287 198.51.100.20
The awk filter keeps only records of the type you asked for, so a CNAME in front of an A record doesn't confuse the comparison. For TXT records, the value includes quotes, so pass the expected text without them and the substring match still works.
Step 4: Check from Other Locations with DNS over HTTPS
Public resolvers use anycast, so 8.8.8.8 answered from London may be a different cache from 8.8.8.8 answered from Singapore. If you don't have servers in other regions, DNS over HTTPS JSON endpoints are a convenient way to query from scripts, CI pipelines or anywhere outbound DNS is blocked.
Google's JSON API:
curl -s "https://dns.google/resolve?name=www.example.com&type=A"
{"Status":0,"TC":false,"RD":true,"RA":true,"AD":false,"CD":false,"Question":[{"name":"www.example.com.","type":1}],"Answer":[{"name":"www.example.com.","type":1,"TTL":300,"data":"198.51.100.20"}]}
Cloudflare's JSON API needs an accept header:
curl -s -H "accept: application/dns-json" \
"https://cloudflare-dns.com/dns-query?name=www.example.com&type=A"
With jq installed, you can pull out just the values and TTLs:
curl -s "https://dns.google/resolve?name=www.example.com&type=A" |
jq -r '.Answer[] | "\(.data) ttl=\(.TTL)"'
If you have servers or cloud functions in several regions, running the same check from each gives you a genuinely worldwide view through your own infrastructure.
A Python Version with dnspython
For more complex checks, the dnspython library (pip install dnspython) makes it easy:
import dns.resolver
NAME = "www.example.com"
RTYPE = "A"
RESOLVERS = {
"Cloudflare": "1.1.1.1",
"Google": "8.8.8.8",
"Quad9": "9.9.9.9",
"OpenDNS": "208.67.222.222",
}
for label, ip in RESOLVERS.items():
r = dns.resolver.Resolver(configure=False)
r.nameservers = [ip]
r.lifetime = 3
try:
answer = r.resolve(NAME, RTYPE)
values = ", ".join(sorted(rr.to_text() for rr in answer))
print(f"{label:<11} {ip:<16} ttl={answer.rrset.ttl:<6} {values}")
except Exception as exc:
print(f"{label:<11} {ip:<16} error: {exc.__class__.__name__}")
Step 5: Estimate How Long Is Left
The worst-case wait for any resolver is the TTL that was on the old record at the moment you made the change. If the old record had a TTL of 86,400 seconds (24 hours), a resolver that cached it just before your change could keep it for up to a day.
You can see the original TTL by asking the authoritative server, or check what it was beforehand if you saved a zone export. The remaining TTL reported by each resolver tells you exactly how long that particular cache has left.
| What you see | What it means |
|---|---|
| Old value, TTL counting down | Normal. It'll update when the TTL reaches zero. |
| Old value, TTL resets to a high number | The resolver is re-fetching the old value. Check your authoritative servers again. |
| New value on some queries, old on others | Different cache nodes behind one anycast address. Wait. |
| No answer or NXDOMAIN | A negative answer is cached, or the record doesn't exist at the source. |
Negative answers have their own cache time. If someone looked up a record before it existed, resolvers cache the "doesn't exist" result for the shorter of the SOA record's minimum field and the SOA record's own TTL. Check it with:
dig example.com SOA +noall +answer
example.com. 3600 IN SOA ns1.example.net. hostmaster.example.com. 2026101703 7200 3600 1209600 300
Here the last field is 300, so a cached "doesn't exist" answer lasts at most five minutes.
Checking Nameserver Changes
When you change your domain's nameservers at the registrar, you're changing the delegation in the parent zone (such as .com), not a record in your own zone. That needs a different check.
First, confirm the TLD servers have the new nameservers. Ask a TLD server directly with recursion off:
dig +norecurse @a.gtld-servers.net example.com NS
;; AUTHORITY SECTION:
example.com. 172800 IN NS ns1.newdns.example.
example.com. 172800 IN NS ns2.newdns.example.
For other TLDs, find a suitable server with dig org NS +short, dig uk NS +short and so on.
Then check what public resolvers think the nameservers are:
dig @8.8.8.8 example.com NS +noall +answer
dig @1.1.1.1 example.com NS +noall +answer
Delegation NS records at many TLDs carry a TTL of 48 hours (172,800 seconds), which is why nameserver changes are slower than record changes. To follow the whole chain from the root, use dig +trace, which ignores caches entirely:
dig +trace www.example.com A
During a nameserver change, make sure both the old and new DNS providers serve the same records. Then it doesn't matter which nameservers a resolver is using, and visitors see no difference while caches catch up.
Common Reasons a Record Never Propagates
If some resolvers still show the old value long after the TTL should have expired, look for these:
- One of your authoritative servers is out of date: Check the SOA serial on each, as in Step 1.
- The domain's nameservers aren't where you edited: You changed records at a provider your domain isn't delegated to. Compare
dig example.com NS +shortwith the provider's dashboard. - DNSSEC is broken: Validating resolvers return SERVFAIL rather than the new value. Test with
dig +cdto bypass validation. - Location-aware answers: Your provider returns different records for different regions by design.
- A CDN or proxy is in front of your site: The DNS answer is the CDN's address, which doesn't change when you move your origin server.
FAQ: Checking DNS Propagation
For ordinary record changes, up to the TTL of the old record, which is often between five minutes and a day. Nameserver changes can take up to 48 hours because the TLD's delegation records usually have long TTLs.
Large public resolvers run many separate caches behind each address. Repeated queries can land on different caches, some of which have the new value and some the old one, until all their TTLs expire.
You can't force other resolvers to drop their cache, but you can lower the record's TTL well before a planned change, and request a purge from Google Public DNS and Cloudflare for their resolvers.
They complement each other. dig against your authoritative servers tells you definitively what you're publishing. Online checkers give a quick view of many resolvers in different countries, which you can't easily get from one machine.
Your browser and operating system have their own caches, and your local resolver may differ from the one you queried with dig. Flush the browser's and system's DNS caches, and check that the old site isn't being served by a CDN or cached in the browser.
Use the same methods with the record type changed, for example dig @8.8.8.8 example.com MX +noall +answer, or select MX or TXT in an online checker. For DKIM and DMARC, query the full name, such as _dmarc.example.com.
Conclusion
Checking DNS propagation is a matter of working outwards from the source. Confirm every authoritative nameserver is serving the new value with the same SOA serial, then look at a spread of public resolvers with an online checker or a few dig commands. The remaining TTL in each answer tells you exactly how long a stale cache has left.
For nameserver changes, check the TLD's delegation directly with dig +norecurse and expect a longer wait. And if a record refuses to update long after its TTL should have expired, stop waiting and look for an out-of-date nameserver, edits made at the wrong provider, or a DNSSEC problem.


