dnsglobe
August 7, 2026 · View on GitHub
A global DNS propagation checker for your terminal — a Rust TUI that queries 34 public DNS resolvers around the world in parallel, compares their answers, and shows the propagation of your record on a world map.

Think dnschecker.org / whatsmydns.net, but in your terminal, with watch mode: start a check and it re-polls until the record has propagated everywhere.
Resolvers span the global anycast networks (Google, Cloudflare, Quad9), North America, Europe, Russia, the Middle East, East Asia, and the southern hemisphere (Telstra AU, SafeSurfer NZ, UOL BR) — each queried directly, so you see every server's own current view of the record.
Each resolver is queried directly (no cache, EDNS0, TCP fallback for
truncated answers), so what you see is each server's own current view of the
record. Answers sharing any record are grouped together — so round-robin DNS
(each resolver caching a different subset of an IP pool) counts as one
consistent answer, not twenty conflicting ones. The propagation gauge shows
how many resolvers are in the majority group; outliers are flagged
≠ DIFFERS once all results are in.
The table fits an 80-column terminal: every resolver's full IPv4 address,
round-trip time, TTL and expiry countdown stay intact, and the per-row
verdict shrinks to the glyph in the left margin (✓ ≠ ! ↻ ∅ ✗) so the answer
keeps the space. The countdown is coarse on purpose — 45s, 4m, 2h, 1d
— since a column of seconds ticking out of unison is noise above a minute.
When the terminal is wide enough, a view of the world appears on the right
with one dot per resolver, colored by status (green agrees, magenta differs,
red error, yellow in flight). The view adapts to the width: terminals ≥157
columns get a flat world map, narrower ones (≥131 columns) get a spinning 3D
globe, which needs fewer columns; resizing across the threshold morphs one
into the other. Ctrl+O toggles map/globe by hand, and --view auto|map|globe
(or view = "..." in the config file) forces a style outright.
Every resolver is asked which of its sites is answering you, via NSID
(RFC 5001) — an EDNS option the answering node fills with its own name
(gpdns-yul, yul01, res721.qyul1, jfk-dns1-02.inet.centurylink.net).
It needs no per-operator support, so resolvers you add yourself can report a
site too. Where NSID names no place, the operator-specific identification
queries take over: Quad9 (TXT id.server.on.quad9.net), Cloudflare
(CH TXT id.server), Google (egress subnet via
TXT o-o.myaddr.l.google.com matched against TXT locations.publicdns.goog),
OpenDNS (TXT debug.opendns.com), CleanBrowsing, and Neustar UltraDNS. The
discovered site shows in the Loc column as →YUL-style codes, and the
resolver's map dot moves to the POP actually serving your queries.
Usage
Install:
brew install 514-labs/tap/dnsglobe # Homebrew (macOS/Linux)
cargo install dnsglobe # from crates.io
yay -S dnsglobe # from archlinux aur (compile from source)
yay -S dnsglobe-bin # from archlinux aur (install prebuilt binary)
nix run github:514-labs/dnsglobe # Nix flakes (builds from source)
# or grab a prebuilt binary from the GitHub Releases page
Run:
dnsglobe # start empty, type a domain
dnsglobe example.com # query immediately and watch
dnsglobe example.com TXT # same, starting on TXT records
dnsglobe --once example.com TXT # no TUI: print results, exit (for scripts)
dnsglobe example.com --ecs 203.0.113.0/24 # see the zone as that client network does
dnsglobe --once example.com --ecs 203.0.113.0/24,198.51.100.0/24
# one table per subnet + a convergence summary
EDNS Client Subnet (ECS)
--ecs (or ecs = [...] in the config file) attaches an EDNS Client Subnet
option (RFC 7871) to every
query, so GeoDNS zones answer for that client network instead of the
resolver's own vantage point. Subnets are CIDRs or bare IPs; most public
resolvers use at most /24 (IPv4) or /56 (IPv6). With several subnets
configured, Ctrl+N cycles the active one (plus an off position) and
re-queries immediately; --once runs every subnet and ends with a
per-subnet convergence summary. Resolvers that deliberately ignore ECS
(Cloudflare, Quad9, …) are tagged NO ECS — their answer is shown for
reference but excluded from the propagation percentage, since it describes
their own location, not the probed network.
Keys
| Key | Action |
|---|---|
| type / ⌫ / Del | edit domain |
| ←/→ / Home/End | move cursor in the domain field |
| Enter | start the check and watch: re-polls every 30 s until propagation reaches 100% |
| Ctrl+R | stop or resume watching |
| Tab / Shift-Tab | select record type (A, AAAA, CNAME, MX, NS, TXT, SOA) and re-query |
| ↑/↓ / PgUp/PgDn | move the highlight through the resolver table (scrolls to follow) |
| + | add a resolver for this session (name, IP, optional location and map position) |
| Ctrl+X | remove the highlighted resolver for this session |
| Ctrl+S | cycle table sort: resolver / location / ping / status / answer |
| Ctrl+O | toggle the world view between flat map and rotating globe |
| Ctrl+N | cycle the ECS client subnet and re-query (only when --ecs/config set one up) |
| Ctrl+U | clear domain |
| Esc / Ctrl+C | quit |
Configuration
Optionally, add your own resolvers — or replace the built-in list entirely —
with a TOML config file at ~/.config/dnsglobe/config.toml
($XDG_CONFIG_HOME/dnsglobe/config.toml if set). Set DNSGLOBE_CONFIG to
use a different path.
# Set to true to replace the built-in list instead of extending it —
# e.g. to watch propagation across your own nameservers only.
replace = false
# EDNS Client Subnet(s) to query with (Ctrl+N cycles; --ecs overrides).
ecs = ["203.0.113.0/24"]
# World-view style: auto (default — pick by terminal width), map, or globe.
# The --view flag overrides this.
view = "auto"
[[resolvers]]
name = "Corp DNS" # required — shown in the Resolver column
ip = "10.0.0.53" # required — IPv4 or IPv6, queried on port 53
location = "HQ" # optional — Loc column / location sort
lat = 40.7 # optional — position on the world map;
lon = -74.0 # omit both to leave it off the map
[[resolvers]]
name = "NS1 (public)"
ip = "198.51.100.53"
# Optionally recolor the UI. Every key is optional; unset roles keep their
# defaults. Colors are ANSI names ("lightcyan"), 256-color indexes ("208"),
# or hex ("#ff8700" — needs truecolor support).
[theme]
accent = "lightcyan" # borders, titles, cursor, anycast sites
agree = "lightgreen" # answers matching the majority; fast latency
differ = "lightmagenta" # answers disagreeing with the majority
error = "white on lightred"
# ERR / SERVFAIL / NONE; slow latency. Written
# "<fg> on <bg>", it becomes a filled badge on the
# status glyph and word — legible on any background;
# a plain color like "lightred" drops the badge
pending = "lightyellow" # queries in flight; middling latency
stale = "208" # caches serving an answer past its own TTL
upstream = "lightblue" # refetched but upstream still has the old data
muted = "faint" # labels, hints, countdowns, quiet borders —
# "faint" dims your terminal's default foreground;
# set a color if your terminal renders faint poorly
coastline = "gray" # map/globe land outline
grid = "244" # globe graticule and limb
Invalid config (bad IP, unknown key, unrecognized color, bad ecs subnet,
lat without lon, replace = true with no resolvers) is reported at
startup with the offending entry named.
Notes
- Several resolvers are anycast networks, so the responding node is the one
nearest to you. Networks that identify their node — via NSID or an
identification query — report the actual answering site (
→YUL); for the rest the location column is the operator's home region. - The built-in resolver list lives in
src/resolvers.rs; use the config file above to extend or replace it without rebuilding. Every built-in entry was verified to answer external queries; many well-known ISP resolvers (and, notably, all major African ones) refuse queries from outside their network, so they can't be included.
Nix
The project provides optional Nix flake outputs for users who already use Nix. The flake builds from source.
# Latest source from default branch
nix run github:514-labs/dnsglobe
# Specific release (uses the flake at that git tag)
nix run github:514-labs/dnsglobe/v0.4.0
# Named outputs (if the flake exposes them): #latest, #source
nix run github:514-labs/dnsglobe#source
# Build / develop
nix build github:514-labs/dnsglobe
nix develop github:514-labs/dnsglobe
The flake exposes packages.<system>.default, apps.<system>.default, devShells.<system>.default, and overlays.default.
Update through the same Nix workflow you used to install. For profile installs, run nix profile list and then nix profile upgrade <index-or-name>. For flake inputs, run nix flake update <repo> in your own flake and rebuild.
Devbox
For reproducible development environments, use Devbox:
# Install Devbox first (if not already installed)
curl -fsSL https://get.jetify.dev/devbox | bash
# Initialize the environment
devbox shell
# Build the project
devbox run build
Or install Devbox via Homebrew:
brew install jetify-com/devbox/devbox
Made with ❤️ by the folks working on 514.ax.