Field notes

Tracking DNS propagation from the command line

 ·  ~5 min read  ·  dig / whois / cloudflare

You have pointed your registrar at new nameservers - say you are moving your-website.com from Namecheap to Cloudflare - and now you want to know when the change has taken. Here is how to watch it happen from a terminal, and what "propagation" actually means.

It is two changes, not one

"DNS propagation" for a nameserver move is really two separate things, and you track them with different queries:

Nothing is ever "pushed." Every resolver just times its own cache out on its own schedule. A command-line check only ever shows your vantage point, plus whichever resolvers you explicitly ask.

The general toolbox

dig does almost everything.

# authoritative walk from the root → .com → your zone (ignores every cache)
dig +trace your-website.com

# what one specific public resolver returns right now (skips your OS stub cache)
dig NS your-website.com @1.1.1.1 +short
dig A  your-website.com @8.8.8.8 +short

# ask the zone's own authoritative servers, and check they all agree
dig +nssearch your-website.com

# registry-level view - updates fast, ahead of resolver caches
whois your-website.com | grep -i 'name server'

# poll a value until it flips
watch -n 30 'dig A your-website.com @1.1.1.1'   # TTL shows in the ANSWER SECTION

dig +trace is the important one: it does the recursion itself starting from the root hints, so it ignores your resolver's cache entirely and shows you what the parent zone is actually handing out.

Other tools, same idea:

Public resolvers worth sampling: 1.1.1.1 (Cloudflare), 8.8.8.8 (Google), 9.9.9.9 (Quad9), 208.67.222.222 (OpenDNS).

The sequence for a Namecheap → Cloudflare move

# 0. capture the two Cloudflare nameservers you were assigned
CF1=xxx.ns.cloudflare.com ; CF2=yyy.ns.cloudflare.com

# 1. did Namecheap push the change to the .com registry? (minutes to hours)
whois your-website.com | grep -i 'name server'
#    → expect XXX.NS.CLOUDFLARE.COM / YYY.NS.CLOUDFLARE.COM

# 2. is the .com TLD actually handing out Cloudflare's nameservers?
#    this is the real cutover point
dig +trace your-website.com | grep -A3 'your-website.com'
#    or ask a .com TLD server directly:
dig NS your-website.com @$(dig +short com NS | head -1)

# 3. is Cloudflare answering authoritatively, with the right data?
#    (works before step 2 finishes - you query its nameservers directly)
dig SOA your-website.com @"$CF1" +short
dig A   your-website.com @"$CF1" +short
dig MX  your-website.com @"$CF1"
dig TXT your-website.com @"$CF1"        # check SPF / DKIM / DMARC survived the move

# 4. what the public resolvers see - done when these all agree
for r in 1.1.1.1 8.8.8.8 9.9.9.9 208.67.222.222; do
  printf '%-16s ' "$r"; dig +short NS your-website.com @$r | paste -sd' '
done

# 5. SSL prerequisites
dig CAA your-website.com +short         # empty = any CA may issue (fine). A restrictive
                                       # record must allow letsencrypt.org / pki.goog
dig DS  your-website.com @$(dig +short com NS | head -1)
#    → if a DS record exists at the parent but you have not re-enabled
#      DNSSEC in Cloudflare, validating resolvers (Quad9, Google) will
#      SERVFAIL. Remove the DS record at Namecheap first.

# 6. once it is live - confirm you are hitting Cloudflare and the cert is valid
curl -sI https://your-website.com | grep -iE '^(server|cf-ray|location):'
echo | openssl s_client -connect your-website.com:443 -servername your-website.com 2>/dev/null \
  | openssl x509 -noout -issuer -subject -dates

Read it top to bottom while the move is in flight. Steps 1 and 3 go green quickly; step 2 is the one you wait on; step 4 is how you know it is finished everywhere that matters.

Flushing your own caches

If a query looks stale, the cache in the way might be yours:

dig +trace and pointing dig straight at an authoritative nameserver sidestep local caching altogether, so reach for those when you want the source of truth rather than your ISP's copy of it.

One last thing

"Propagation" is a slightly misleading word - there is no wavefront moving out from your registrar. There is only a large number of independent caches, each holding the old answer until its TTL runs out, then asking again. Lower your record TTLs a day before you move and most of that tail disappears.

If you would rather watch it on a map than in a for loop, that is more or less what this site does - the NS · registrar transfer preset simulates exactly this scenario.