// ...
[2026-01-31T02:35:27.109Z] [ 9/10] [
{
host: 'python.org',
latency: 5,
resolved: [
{ address: '151.101.64.223', ttl: 214, type: 'A' },
{ address: '151.101.0.223', ttl: 214, type: 'A' },
{ address: '151.101.128.223', ttl: 214, type: 'A' },
{ address: '151.101.192.223', ttl: 214, type: 'A' },
{ address: '2a04:4e42:600::223', ttl: 214, type: 'AAAA' },
{ address: '2a04:4e42:400::223', ttl: 214, type: 'AAAA' },
{ address: '2a04:4e42:200::223', ttl: 214, type: 'AAAA' },
{ address: '2a04:4e42::223', ttl: 214, type: 'AAAA' },
{ value: 'ns-2046.awsdns-63.co.uk', type: 'NS' },
{ value: 'ns-981.awsdns-58.net', type: 'NS' },
{ value: 'ns-484.awsdns-60.com', type: 'NS' },
{ value: 'ns-1134.awsdns-13.org', type: 'NS' },
{ entries: [ '888acb5757da46ad83b7e341ec544c64' ], type: 'TXT' },
{ entries: [ 'libera-1298aas' ], type: 'TXT' },
{ entries: [ 'google-site-verification=9852CbTRhQ51-9gCUayPbGYqJeBle_MXLb6E4AL_qQk' ], type: 'TXT' },
{ entries: [ 'google-site-verification=w3b8mU3wU6cZ8uSrj3E_5f1frPejJskDpSp_nMWJ99o' ], type: 'TXT' },
{ entries: [ 'google-site-verification=QALZObrGl2OVG8lWUE40uVSMCAka316yADn9ZfCU5OA' ], type: 'TXT' },
{ entries: [ 'google-site-verification=dqhMiMzpbkSyEhgjGKyEOMlEg2tF0MSHD7UN-MYfD-M' ], type: 'TXT' },
{ entries: [ '_globalsign-domain-verification=B57sRQpmte4G4w-gavZbVNmmNsMxGp5kcL19UP2599' ], type: 'TXT' },
{ entries: [ 'status-page-domain-verification=9y2klhzbxsgk' ], type: 'TXT' },
{ entries: [ 'MS=73147F1EC0843C399CF17F586EC6B8EAF8C57961' ], type: 'TXT' },
{ entries: [ 'v=spf1 mx ip4:188.166.95.178/32 ip6:2a03:b0c0:2:d0::71:1 include:stspg-customer.com include:_spf.google.com include:mailgun.org ~all' ], type: 'TXT' },
{ entries: [ 'twilio-domain-verification=1c295667813cc0aaae819ed7657818f8' ], type: 'TXT' },
{ nsname: 'ns-2046.awsdns-63.co.uk', hostmaster: 'awsdns-hostmaster.amazon.com', serial: 1, refresh: 7200, retry: 900, expire: 1209600, minttl: 86400, type: 'SOA' }
]
},
{ host: 'mail.python.org', latency: 0, resolved: [ { address: '188.166.95.178', ttl: 86190, type: 'A' }, { address: '2a03:b0c0:2:d0::71:1', ttl: 86190, type: 'AAAA' } ] },
{ host: 'front.python.org', latency: 1, resolved: [ { address: '140.211.10.69', ttl: 86331, type: 'A' } ] }
]
┌──────────────────┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ (index) │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │
├──────────────────┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
│ python.org │ 3 │ 3 │ 9 │ 8 │ 7 │ 6 │ 5 │ 7 │ 7 │ 5 │
│ mail.python.org │ 1 │ 9 │ 0 │ 1 │ 1 │ 5 │ 3 │ 1 │ 9 │ 0 │
│ front.python.org │ 1 │ 1 │ 6 │ 1 │ 1 │ 1 │ 1 │ 3 │ 5 │ 1 │
└──────────────────┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
┌──────────────────┬───────────────────┬───────────────────┬───────────────────┬───────────────────┬──────────────────┬──────────────────┬──────────────────┬───────────────────┬───────────────────┬──────────────────┐
│ (index) │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │
├──────────────────┼───────────────────┼───────────────────┼───────────────────┼───────────────────┼──────────────────┼──────────────────┼──────────────────┼───────────────────┼───────────────────┼──────────────────┤
│ python.org │ '151.101.192.223' │ '151.101.192.223' │ '151.101.128.223' │ '151.101.128.223' │ '151.101.0.223' │ '151.101.64.223' │ '151.101.0.223' │ '151.101.128.223' │ '151.101.192.223' │ '151.101.64.223' │
│ mail.python.org │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │ '188.166.95.178' │
│ front.python.org │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │ '140.211.10.69' │
└──────────────────┴───────────────────┴───────────────────┴───────────────────┴───────────────────┴──────────────────┴──────────────────┴──────────────────┴───────────────────┴───────────────────┴──────────────────┘
Last active
January 31, 2026 02:48
-
-
Save serious-angel/f6c25f177c840a6e36ac08bf0d3c2d85 to your computer and use it in GitHub Desktop.
DNS Latency Node v21+ script example
# 1. Monitor DNS resolution activity.
sudo resolvectl monitor 2>&1 \
| grep -P --line-buffered -- '(A: .*python.* A .+|Q: .*python.* A)$' \
| TZ= ts '[ %F_%H-%M-%.SZ ] ';
# 2. Loop over a few DNS resolution attempts.
# cd -- "$( mktemp -d; )" &&
npm i --prefix "$( pwd -P; )" -- 'node-fetch' &&
node -v &&
node -- ./dns_latency.mjs 10 python.org mail front;
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /usr/bin/env node | |
| import fetch from 'node-fetch'; | |
| import dns from 'dns'; | |
| import util from 'util'; | |
| async function resolveDns(domain, subdomains) { | |
| const resolutions = []; | |
| for (const s of ['', ...subdomains]) { | |
| const host = `${s}${s && '.'}${domain}`; | |
| const startedAt = Date.now(); | |
| resolutions.push(await new Promise(r => dns.resolveAny(host, (_, v) => r(v))).then(resolved => ({ | |
| host, | |
| latency: Date.now() - startedAt, | |
| resolved, | |
| }))); | |
| } | |
| return resolutions; | |
| } | |
| async function main(args) { | |
| const count = args.shift() || 0; | |
| const domain = args.shift() || ''; | |
| const subdomains = args; | |
| // IP address | |
| // -------------------------------- | |
| await fetch('https://ipinfo.io/', { | |
| method: 'post', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'User-Agent': 'curl' | |
| } | |
| }) | |
| .then(r => r.text()) | |
| .then(console.log); | |
| // DNS servers | |
| // -------------------------------- | |
| console.log({ dns: dns.getServers() }); | |
| if (!/^(0|[1-9][0-9]*)$/.test(count) || count <= 0 || !domain?.length) { | |
| return; | |
| } | |
| // DNS resolutions | |
| // -------------------------------- | |
| const resolved = { | |
| latencies: {}, | |
| addresses: {} | |
| }; | |
| for (let i = 0; i < count; i++) { | |
| const resolutions = await resolveDns(domain, subdomains); | |
| console.log( | |
| `[${new Date().toISOString()}] [${String(i).padStart(String(count).length, ' ')}/${count}]`, | |
| util.inspect(resolutions, { | |
| depth: 5, | |
| breakLength: 200 | |
| } | |
| )); | |
| resolutions.forEach(r => { | |
| const latency = r.latency; | |
| const address = r.resolved?.[0]?.address; | |
| resolved.latencies[r.host] = resolved.latencies[r.host]?.concat(latency) || [latency]; | |
| resolved.addresses[r.host] = resolved.addresses[r.host]?.concat(address) || [address]; | |
| }); | |
| } | |
| console.table(resolved.latencies); | |
| console.table(resolved.addresses); | |
| } | |
| main(process.argv.slice(2)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment