DNS Cheatsheet

dig

Use this DNS reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

Query anatomy

dig [@server] [name] [type] [+options] [-flags]
dig example.com                    # A record, system resolver
dig example.com MX                 # a specific type
dig @1.1.1.1 example.com AAAA      # a specific resolver
dig -t MX example.com              # explicit -t, needed if the name looks like a type

Order is flexible, dig MX example.com works too, but @server must precede the name it applies to when you pass several.

The output sections

; <<>> DiG 9.10.6 <<>> example.com A
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41005
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232

;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       93.184.215.14

;; Query time: 15 msec
;; SERVER: 1.1.1.1#53(1.1.1.1)
;; WHEN: Tue Sep 15 19:13:44 PDT 2026
;; MSG SIZE  rcvd: 72
SectionRead it for
HEADERstatus: is the RCODE, id: matches request to response
flags:aa authoritative, ra recursion available, tc truncated, ad DNSSEC validated
OPT PSEUDOSECTIONEDNS(0) buffer size, DO bit, NSID
QUESTIONWhat was actually asked after search-list expansion
ANSWERThe records. Empty with NOERROR means NODATA
AUTHORITYNS records on a referral, or the SOA on NXDOMAIN/NODATA
ADDITIONALGlue addresses for the names above
SERVERWhich resolver answered. Check this before trusting anything

Trimming the output

+short for scripts, +noall +answer when you want the TTL and type too.

dig example.com +short              # 93.184.215.14, one per line
dig example.com MX +short           # 10 mx1.example.com.
dig example.com +noall +answer      # the answer section, formatted
dig example.com +noall +authority   # just the authority section
dig example.com +nocmd +nocomments +nostats
dig example.com +multiline          # expanded, one field per line, with names
dig example.com ANY +noall +answer +multiline

+all and +noall set or clear every display flag at once, so the idiom is +noall followed by the sections you want back.

OptionEffect
+shortBare RDATA only, no headers, no TTLs
+noall +answerAnswer section only, full record format
+nocmdDrop the ; <<>> DiG echo line
+nostatsDrop the query time and SERVER footer
+multilineExpand records, annotate DNSSEC fields, split base64
+ttlid / +nottlidShow or hide TTLs
+identifyWith +short, append which server answered

Delegation, authority, and trace

dig example.com NS +short              # the zone's nameservers
dig example.com SOA +short             # serial and negative TTL
dig com NS +short                      # the TLD's nameservers
dig +trace example.com A               # walk root -> TLD -> authoritative
dig +nssearch example.com              # SOA from every authoritative server

Ask an authoritative server directly, without recursion, which is how you tell "the zone is wrong" from "a cache is stale":

dig @ns1.example.com example.com A +norecurse
dig @ns1.example.com example.com A +norecurse +noall +answer +comments

+norecurse against a resolver returns only what is already cached, so it is the way to inspect a cache without warming it.

+nssearch queries every NS in turn and prints each SOA, which makes a disagreeing secondary obvious at a glance:

SOA ns1.example.com. hostmaster.example.com. 2026091501 ... from server 198.51.100.10
SOA ns2.example.com. hostmaster.example.com. 2026091499 ... from server 198.51.100.11

Different serials mean a zone transfer is broken.

Reverse, transport, and DNSSEC

dig -x 8.8.8.8 +short                  # reverse IPv4, builds in-addr.arpa for you
dig -x 2001:4860:4860::8888 +short     # reverse IPv6, ip6.arpa
dig 8.8.8.8.in-addr.arpa PTR           # the long form -x expands to

dig example.com A +tcp                 # force TCP 53
dig example.com A -4                   # IPv4 transport only
dig example.com A -6                   # IPv6 transport only
dig example.com A -p 5353              # non-standard port
dig example.com A +bufsize=4096        # bigger EDNS(0) buffer
dig example.com A +noedns              # no EDNS at all, 512-byte cap

dig cloudflare.com A +dnssec           # request RRSIG records
dig cloudflare.com DNSKEY +multiline
dig com DS +short                      # the delegation signer at the parent
dig example.com A +cdflag              # ask the resolver NOT to validate

+dnssec sets the DO bit. An ad flag in the response means the resolver validated the chain. +cdflag disables that validation, so a query that fails without +cdflag and succeeds with it is a DNSSEC problem, not a data problem.

Timing, retries, and batches

dig example.com +time=2 +tries=1       # fail fast instead of the 5s × 3 default
dig example.com +retry=0               # no UDP retries
dig example.com A example.net A example.org A   # three queries, one invocation
dig -f names.txt +short                # one name per line from a file
dig @ns1.example.com example.com AXFR  # full zone transfer, TCP, usually refused
dig example.com A +subnet=203.0.113.0/24   # test geo-aware answers
dig example.com A +nsid                # ask which anycast node answered

Defaults are +time=5 and +tries=3, so an unreachable server costs 15 seconds before dig gives up. Always pass +time and +tries in a loop or a health check.

A refused transfer looks like this, and is the correct configuration for a public server:

; Transfer failed.

Scripting patterns

# exit non-zero if a name does not resolve
dig +short example.com A | grep -q . || echo "no A record"

# the RCODE, for a conditional
rc=$(dig example.com A | awk -F'status: ' '/status:/{print $2}' | cut -d, -f1)

# compare every authoritative server for the same record
for ns in $(dig +short example.com NS); do
  printf '%-28s %s\n' "$ns" "$(dig @"$ns" +short example.com A | tr '\n' ' ')"
done

# TTL only
dig example.com A +noall +answer | awk '{print $2}'

# has the change propagated to the big public resolvers
for r in 8.8.8.8 1.1.1.1 9.9.9.9 208.67.222.222; do
  printf '%-16s %s\n' "$r" "$(dig @$r +short api.example.com A | tr '\n' ' ')"
done

Gotchas

- dig ignores /etc/hosts and nsswitch.conf. It talks to port 53 directly. dig succeeding while your application fails is a system-resolver problem, so cross-check with getent hosts name. - dig does use the search list for names without a trailing dot. Add the dot (dig example.com.) or +nosearch when a short name is being expanded behind your back. - Check the SERVER: footer before believing an answer. On a laptop it is often 127.0.0.53 or a VPN resolver, not what you assumed. - +short hides the RCODE. An empty +short output means either NXDOMAIN, NODATA, or SERVFAIL, and you cannot tell which. Drop +short when debugging. - +trace starts from the root and does its own recursion, so it bypasses your resolver's cache entirely. That is the point, and it also means a +trace that works while a normal query fails points at your resolver. - dig ANY is not a zone dump and most servers refuse it. Use AXFR if you are permitted, otherwise enumerate the types you care about. - dig is in bind-utils (RHEL), dnsutils (Debian), and bind-tools (Alpine). BIND 9.18 and newer also ship delv, which validates DNSSEC and prints a plain answer.