dnsquery is a DNS stub client that queries record types for many domains at once – from arguments, a file, or stdin – and writes the results as text, YAML, JSON, CSV or (optionally) Excel.
It sends recursive queries to your resolvers (it is not an iterative resolver) and follows standards-aligned response handling: EDNS(0), TCP fallback on truncation, NXDOMAIN vs. NODATA with negative-caching TTLs, failover across redundant nameservers, a per-run cache, and optional local DNSSEC validation from the root trust anchor.
$ dnsquery example.com
QUERY STATUS NAME TYPE TTL VALUE
example.com NOERROR example.com. A 300 172.66.147.243
example.com NOERROR example.com. A 300 104.20.23.154
What it does
- Bulk lookups. Domains come from arguments,
--file, or stdin. Blank lines and#comments are skipped, and internationalized names work as typed (räksmörgås.seis queried asxn--rksmrgs-5wao1o.se). - Structured output. Text, YAML, JSON, CSV or Excel, with the columns
you choose via
--select-fields(dnsquery --list-fieldslists them). There is one row per answer record, or a single row for a negative or failed response. - Honest status codes.
NODATA(the name exists but has no records of that type) andERROR(no usable response) are kept apart fromNXDOMAIN, a definite “this name does not exist”. - Filtering.
--match-fieldskeeps only matching rows, with case-insensitive substrings,|alternatives and&&conditions. - Plain-language explanations.
--explainadds a column that says what each answer means. - Nameserver health checks.
--check-nameserversasks every authoritative nameserver of a zone directly and reports lame servers, serial mismatches and differing answers. - DNSSEC validation. With
--dnssec, dnsquery acts as a validating stub resolver: it checks the signatures itself instead of trusting the resolver’s AD bit, and reports each answer assecure,insecureorbogus. - Built for large inputs. Rate limiting (
--rate, default 15 queries per second), bounded concurrency, and streaming output in input order keep memory flat: 500,000 domains peak at 36-90 MB depending on format.
Quick start
Requires Go 1.26+. Build a static dnsquery binary for linux/amd64:
./compile
Excel output is optional, because the library behind it about doubles the binary:
TAGS=excel ./compile
Then query:
dnsquery example.com
dnsquery example.com --type MX
dnsquery --file domains.txt
printf "example.com\nexample.org\n" | dnsquery --type A
dnsquery 192.0.2.1 --type PTR # IPs are reversed for PTR
dnsquery example.com --server 1.1.1.1,9.9.9.9 # tried in order
Filter results:
dnsquery --file domains.txt --type MX --match-fields 'status=NOERROR&&value=google|outlook'
dnsquery --file domains.txt --match-fields status=NXDOMAIN,query=.se
Check a zone’s nameservers:
$ dnsquery --check-nameservers nic.se --select-fields ns,server,status,serial,nsid,check
NS SERVER STATUS SERIAL NSID CHECK
ns.iis.se. 91.226.36.45:53 NOERROR 1790773966
ns3.iis.se. 91.226.37.45:53 NOERROR 1790773966
nsa.dnsnode.net. 194.58.192.46:53 NOERROR 1790773966 s4.got
...
Validate with DNSSEC:
$ printf "example.com\ngoogle.com\ndnssec-failed.org\nnonexistent-zz9q.se\n" | dnsquery --dnssec --select-fields query,status,dnssec,dnssec_reason
QUERY STATUS DNSSEC DNSSEC_REASON
example.com NOERROR secure
example.com NOERROR secure
google.com NOERROR insecure insecure delegation: google.com. has no DS in com.
dnssec-failed.org NOERROR bogus no DNSKEY for dnssec-failed.org. matches its DS records or trust anchors
nonexistent-zz9q.se NXDOMAIN secure
1 of 4 queries failed (1 DNSSEC bogus)
Settings can also live in ~/.dnsquery.yaml; generate a commented example
with:
dnsquery --config-example > ~/.dnsquery.yaml
Exit status
| Code | Meaning |
|---|---|
| 0 | Every query got a DNS answer (NXDOMAIN and SERVFAIL are answers) |
| 1 | Usage, configuration, input or output error, or interrupted |
| 2 | At least one query ended in ERROR, was DNSSEC bogus with --dnssec, or found a nameserver problem with --check-nameservers; results are still written |
dnsquery is BSD 2-Clause licensed. The full flag reference, output fields and the RFCs it follows are in the README on GitHub.