ZetCode

Linux dig and nslookup Commands

last modified October 23, 2026

The dig and nslookup commands query the Domain Name System (DNS). They show which addresses a name resolves to, which servers handle mail for a domain, which name servers are authoritative for it, and much more. dig (domain information groper) shows the DNS response in detail and is the tool of choice for troubleshooting; nslookup is older, simpler, and also available on Windows.

Both come from the BIND project; on Debian and Ubuntu they are in the bind9-dnsutils package (dnsutils on older releases), on Fedora in bind-utils. The examples were run on Ubuntu 22.04 with BIND 9.18, which uses the local systemd-resolved stub resolver at 127.0.0.53. The answers come from the live DNS, so the addresses and TTL values will differ when you run the commands.

A basic query

Without options, dig asks for the A record (the IPv4 address) of a name.

dig example.com

The output mirrors the DNS message. The header shows the status (NOERROR means success) and the flags: qr marks a response, rd says that we asked for recursion, and ra that the server offers it. The question section repeats what we asked; the answer section holds the records. Each record has five fields: name, TTL in seconds, class (IN for Internet), type, and data. Here, example.com has two IPv4 addresses. The last lines show the query time and the server that answered, the local resolver.

$ dig example.com

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

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		144	IN	A	104.20.23.154
example.com.		144	IN	A	172.66.147.243

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Fri Oct 23 21:44:15 CEST 2026
;; MSG SIZE  rcvd: 72

Short output

The +short option prints only the data of the answer.

dig +short example.com
dig +short zetcode.com

Options that start with + are query options, specific to dig. They can be placed anywhere on the command line. The order of multiple records may change from query to query; resolvers rotate them to spread the load.

$ dig +short example.com
104.20.23.154
172.66.147.243
$ dig +short zetcode.com
164.92.191.90

Record types

The record type follows the name. The most common types are summarized in the following table.

TypeContent
AIPv4 address
AAAAIPv6 address
CNAMEAlias: the canonical name of the host
MXMail server with a preference number
NSAuthoritative name server of the zone
TXTFree text: SPF, domain verification tokens
SOAStart of authority: zone parameters
PTRName for an address (reverse lookup)
SRVHost and port of a service
CAACertificate authorities allowed to issue certificates
dig +short example.com AAAA
dig +short gnu.org MX
dig +short example.com NS
dig +short example.com TXT
dig +short example.com SOA

The mail server of gnu.org is eggs.gnu.org, with preference 10; with several MX records, the lowest number is tried first. example.com is served by Cloudflare name servers. Its SPF record v=spf1 -all says that no server may send mail for the domain. The SOA record lists the primary name server, the mailbox of the administrator (dns.cloudflare.com stands for dns@cloudflare.com), the serial number, and timers.

$ dig +short example.com AAAA
2606:4700:10::6814:179a
2606:4700:10::ac42:93f3
$ dig +short gnu.org MX
10 eggs.gnu.org.
$ dig +short example.com NS
elliott.ns.cloudflare.com.
hera.ns.cloudflare.com.
$ dig +short example.com TXT
"_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"
"v=spf1 -all"
$ dig +short example.com SOA
elliott.ns.cloudflare.com. dns.cloudflare.com. 2418004112 10000 2400 604800 1800

Controlling the output

The +noall option turns off all output sections, and other options turn the wanted ones back on. +noall +answer is the most useful combination: full records without the rest.

dig +noall +answer gnu.org MX
dig +noall +answer www.kernel.org

Unlike +short, this shows names, TTLs, and types. The second query shows a CNAME chain: www.kernel.org is an alias for a name at the Fastly content delivery network, which has the A record. The resolver follows the chain and returns all records. A CNAME cannot coexist with other records of the same name, so the apex of a domain, such as kernel.org, never has one.

$ dig +noall +answer gnu.org MX
gnu.org.		235	IN	MX	10 eggs.gnu.org.
$ dig +noall +answer www.kernel.org
www.kernel.org.		60	IN	CNAME	dualstack.m.sni.global.fastly.net.
dualstack.m.sni.global.fastly.net. 25 IN A	199.232.17.55

Multiline output

The +multiline option prints long records such as SOA over several lines, with comments.

dig +noall +answer +multiline example.com SOA

The serial number changes with every update of the zone. The refresh, retry, and expire timers control secondary servers that copy the zone. The last value is the TTL for negative answers: a resolver caches the fact that a name does not exist for 30 minutes.

$ dig +noall +answer +multiline example.com SOA
example.com.		1542 IN	SOA elliott.ns.cloudflare.com. dns.cloudflare.com. (
				2418004112 ; serial
				10000      ; refresh (2 hours 46 minutes 40 seconds)
				2400       ; retry (40 minutes)
				604800     ; expire (1 week)
				1800       ; minimum (30 minutes)
				)

Querying a specific server

A server name or address prefixed with @ sends the query to that server instead of the system resolver.

dig @1.1.1.1 example.com +noall +answer +stats
dig @8.8.8.8 +short gnu.org

1.1.1.1 is Cloudflare's public resolver and 8.8.8.8 Google's. Comparing answers from several resolvers helps find out whether a problem lies with the local resolver, for example a stale cache, or with the domain itself. The +stats option adds the query time and the server.

$ dig @1.1.1.1 example.com +noall +answer +stats
example.com.		266	IN	A	104.20.23.154
example.com.		266	IN	A	172.66.147.243
;; Query time: 4 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Fri Oct 23 21:44:15 CEST 2026
;; MSG SIZE  rcvd: 72

$ dig @8.8.8.8 +short gnu.org
209.51.188.116

Asking an authoritative server

Resolvers such as 1.1.1.1 look names up on behalf of clients and cache the results. Authoritative servers hold the zone data. We can find them with an NS query and ask them directly.

dig +short example.com NS
dig @elliott.ns.cloudflare.com example.com

The response has the aa (authoritative answer) flag and lacks ra: authoritative servers do not resolve other names for us, which the warning points out. The TTL is the full value configured in the zone, 300 seconds. Asking the authoritative server is how we verify a DNS change right after making it, before caches expire.

$ dig +short example.com NS
elliott.ns.cloudflare.com.
hera.ns.cloudflare.com.
$ dig @elliott.ns.cloudflare.com example.com

; <<>> DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu <<>> @elliott.ns.cloudflare.com example.com
; (6 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27749
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.			IN	A

;; ANSWER SECTION:
example.com.		300	IN	A	172.66.147.243
example.com.		300	IN	A	104.20.23.154

;; Query time: 3 msec
;; SERVER: 108.162.195.228#53(elliott.ns.cloudflare.com) (UDP)
;; WHEN: Fri Oct 23 21:44:15 CEST 2026
;; MSG SIZE  rcvd: 72

TTL and caching

The TTL in an answer from a resolver counts down while the record sits in its cache.

dig +noall +answer gnu.org
sleep 5
dig +noall +answer gnu.org
dig @8.8.8.8 +noall +answer gnu.org

Five seconds later, the local resolver returns the same record with a TTL five seconds lower. Google's resolver has its own cache, with its own countdown. When a record changes, clients may see the old value until the TTL runs out in every cache on the way; this is why administrators lower the TTL ahead of a planned change.

$ dig +noall +answer gnu.org
gnu.org.		175	IN	A	209.51.188.116
$ sleep 5
$ dig +noall +answer gnu.org
gnu.org.		170	IN	A	209.51.188.116
$ dig @8.8.8.8 +noall +answer gnu.org
gnu.org.		266	IN	A	209.51.188.116

Reverse lookups

The -x option looks up the name of an IP address. It builds the PTR query for the special in-addr.arpa domain, with the address bytes reversed.

dig -x 8.8.8.8 +short
dig -x 1.1.1.1 +noall +answer

Reverse records are maintained by the owner of the address block, not of the domain, so many addresses have no PTR record, or one with a generic name from the hosting provider. Mail servers often check them.

$ dig -x 8.8.8.8 +short
dns.google.
$ dig -x 1.1.1.1 +noall +answer
1.1.1.1.in-addr.arpa.	1480	IN	PTR	one.one.one.one.

Names that do not exist

The status field in the header tells why there is no answer.

dig no-such-host.gnu.org
echo $?

NXDOMAIN means the name does not exist. The authority section holds the SOA record of the zone; its last field sets how long resolvers may cache this negative answer. Note that dig exits with status 0: it got an answer, even though the answer is negative. In scripts, check the status or the output, not the exit code.

$ dig no-such-host.gnu.org

; <<>> DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu <<>> no-such-host.gnu.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 45355
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;no-such-host.gnu.org.		IN	A

;; AUTHORITY SECTION:
gnu.org.		286	IN	SOA	ns1.gnu.org. hostmaster.gnu.org. 2026071502 3600 120 1209600 3600

;; Query time: 56 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Fri Oct 23 21:44:21 CEST 2026
;; MSG SIZE  rcvd: 100

$ echo $?
0

Names without the requested record

A name can exist but have no records of the requested type.

dig +noall +comments +answer +authority www.gnu.org MX

The status is NOERROR, but the answer section is empty (ANSWER: 0). This is called a NODATA response: www.gnu.org exists, it just has no MX record. Looking only at +short output, NODATA and NXDOMAIN look the same: empty. The +comments option shows the header lines.

$ dig +noall +comments +answer +authority www.gnu.org MX
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14913
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; AUTHORITY SECTION:
gnu.org.		286	IN	SOA	ns1.gnu.org. hostmaster.gnu.org. 2026071502 3600 120 1209600 3600

Unreachable servers and timeouts

The +time option sets the timeout for one attempt in seconds (default 5), and +tries the number of attempts (default 3).

dig @192.0.2.1 example.com +time=1 +tries=2
echo $?

Nothing listens at 192.0.2.1, an address reserved for documentation. After two attempts, dig gives up and exits with status 9 (no reply from server). Status 0 means a response arrived, 1 a usage error, 8 a problem with the batch file, and 10 an internal error.

$ dig @192.0.2.1 example.com +time=1 +tries=2
;; communications error to 192.0.2.1#53: timed out
;; communications error to 192.0.2.1#53: timed out

; <<>> DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu <<>> @192.0.2.1 example.com +time=1 +tries=2
; (1 server found)
;; global options: +cmd
;; no servers could be reached
$ echo $?
9

Tracing the resolution

The +trace option makes dig resolve the name itself, step by step, starting from the root servers, instead of asking a resolver.

dig -4 +trace +nodnssec example.com

The first step gets the list of root servers from the local resolver. A root server refers dig to the servers of the com top-level domain; one of those refers it to the Cloudflare name servers of example.com, which give the final answer. +nodnssec hides the signature records, and -4 uses only IPv4. Without -4, on a host without IPv6 connectivity, the output is mixed with network unreachable errors for the IPv6 addresses of the servers. A trace shows where a delegation is broken, for example when the parent zone lists name servers that do not answer.

$ dig -4 +trace +nodnssec example.com

; <<>> DiG 9.18.39-0ubuntu0.22.04.7-Ubuntu <<>> -4 +trace +nodnssec example.com
;; global options: +cmd
.			7165	IN	NS	j.root-servers.net.
.			7165	IN	NS	f.root-servers.net.
.			7165	IN	NS	l.root-servers.net.
.			7165	IN	NS	c.root-servers.net.
.			7165	IN	NS	b.root-servers.net.
.			7165	IN	NS	d.root-servers.net.
.			7165	IN	NS	g.root-servers.net.
.			7165	IN	NS	i.root-servers.net.
.			7165	IN	NS	k.root-servers.net.
.			7165	IN	NS	e.root-servers.net.
.			7165	IN	NS	m.root-servers.net.
.			7165	IN	NS	h.root-servers.net.
.			7165	IN	NS	a.root-servers.net.
;; Received 239 bytes from 127.0.0.53#53(127.0.0.53) in 0 ms

com.			172800	IN	NS	j.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
com.			172800	IN	NS	l.gtld-servers.net.
com.			172800	IN	NS	f.gtld-servers.net.
com.			172800	IN	NS	k.gtld-servers.net.
com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	d.gtld-servers.net.
com.			172800	IN	NS	h.gtld-servers.net.
com.			172800	IN	NS	e.gtld-servers.net.
com.			172800	IN	NS	g.gtld-servers.net.
com.			172800	IN	NS	i.gtld-servers.net.
com.			172800	IN	NS	c.gtld-servers.net.
com.			172800	IN	NS	m.gtld-servers.net.
;; Received 864 bytes from 192.33.4.12#53(c.root-servers.net) in 5 ms

example.com.		172800	IN	NS	hera.ns.cloudflare.com.
example.com.		172800	IN	NS	elliott.ns.cloudflare.com.
;; Received 359 bytes from 192.35.51.30#53(f.gtld-servers.net) in 36 ms

example.com.		300	IN	A	104.20.23.154
example.com.		300	IN	A	172.66.147.243
;; Received 72 bytes from 108.162.195.228#53(elliott.ns.cloudflare.com) in 6 ms

DNSSEC

DNSSEC signs DNS records, so a resolver can verify that the answers are genuine. The +dnssec option requests the signatures.

dig @1.1.1.1 example.com +dnssec +noall +comments | grep flags
dig @1.1.1.1 example.com +dnssec +noall +answer

The ad (authenticated data) flag means that the resolver validated the signatures. The do flag in the EDNS line is the "DNSSEC OK" bit that dig sent. The RRSIG record is the signature of the A records, with algorithm 13 (ECDSA P-256 with SHA-256), its validity period, and the key tag.

$ dig @1.1.1.1 example.com +dnssec +noall +comments | grep flags
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
; EDNS: version: 0, flags: do; udp: 1232
$ dig @1.1.1.1 example.com +dnssec +noall +answer
example.com.		258	IN	A	104.20.23.154
example.com.		258	IN	A	172.66.147.243
example.com.		258	IN	RRSIG	A 13 2 300 20261024204340 20261022184340 34505 example.com. 3EUyS80evtUQ5jWQiWZKzh4lE6EX6Pbz7awuwIcoHeiKN3ETWapq1+40 JzQyNjKCjrXniCDnoIARZufkrQw6vA==

Querying many names

The -f option reads queries from a file, one per line.

cat domains.txt
dig -f domains.txt +noall +answer

Each line may contain a full query, including a type and options, such as gnu.org MX +short. The options on the command line apply to all queries.

$ cat domains.txt
example.com
gnu.org
kernel.org
$ dig -f domains.txt +noall +answer
example.com.		136	IN	A	104.20.23.154
example.com.		136	IN	A	172.66.147.243
gnu.org.		257	IN	A	209.51.188.116
kernel.org.		265	IN	A	172.105.4.254

Using dig in scripts

+short output is easy to process in shell scripts. The following script prints the preferred mail server of each domain.

cat check-mx.sh
bash check-mx.sh gnu.org example.com no-such-domain-xyz.com

example.com has a null MX record, 0 ., which says that the domain does not accept mail at all (RFC 7505). For the nonexistent domain, the output is empty. With several MX records, sort -n puts the lowest preference first.

$ cat check-mx.sh
#!/bin/bash

for domain in "$@"; do
    mx=$(dig +short "$domain" MX)
    if [ -z "$mx" ]; then
        echo "$domain: no MX records"
    elif [ "$mx" = "0 ." ]; then
        echo "$domain: does not accept mail (null MX)"
    else
        echo "$domain: $(echo "$mx" | sort -n | head -1 | cut -d' ' -f2)"
    fi
done
$ bash check-mx.sh gnu.org example.com no-such-domain-xyz.com
gnu.org: eggs.gnu.org.
example.com: does not accept mail (null MX)
no-such-domain-xyz.com: no MX records

The ANY query

The ANY type used to return all records of a name. It was abused for amplification attacks, and RFC 8482 allows servers to refuse it.

dig @1.1.1.1 +noall +comments example.com ANY

Cloudflare's resolver answers NOTIMP (not implemented), with an extended error code saying so. Other servers return a single record or a synthetic HINFO record. To see the records of a name, query the types one by one.

$ dig @1.1.1.1 +noall +comments example.com ANY
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOTIMP, id: 62074
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; EDE: 21 (Not Supported)

dig and /etc/hosts

dig talks to DNS servers directly. It does not read /etc/hosts or use the other sources configured in /etc/nsswitch.conf, which ordinary programs use through the system library. The getent command shows what those programs see. This example was run in a Debian container, where the name myapp was added to /etc/hosts.

grep myapp /etc/hosts
getent hosts myapp
dig +short myapp
getent hosts example.com

getent finds myapp, dig does not. When a browser and dig disagree, check /etc/hosts first. getent hosts prefers IPv6 addresses; getent ahosts lists all of them.

$ grep myapp /etc/hosts
10.0.0.5	myapp
$ getent hosts myapp
10.0.0.5        myapp
$ dig +short myapp
$ getent hosts example.com
2606:4700:10::ac42:93f3 example.com
2606:4700:10::6814:179a example.com

The nslookup command

nslookup prints the answers in a simpler, more readable form.

nslookup example.com

The first two lines show the server used. Non-authoritative answer means that the answer comes from a resolver's cache, not from an authoritative server. Without a type, nslookup asks for both A and AAAA records.

$ nslookup example.com
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
Name:	example.com
Address: 104.20.23.154
Name:	example.com
Address: 172.66.147.243
Name:	example.com
Address: 2606:4700:10::ac42:93f3
Name:	example.com
Address: 2606:4700:10::6814:179a

Record types, servers, and reverse lookups

The -type option selects the record type, and a second argument the server.

nslookup -type=mx gnu.org
nslookup example.com 1.1.1.1
nslookup 8.8.8.8

An IP address as the argument makes nslookup do a reverse lookup automatically. The empty Authoritative answers can be found from heading is printed by this version even when there is nothing to list under it.

$ nslookup -type=mx gnu.org
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
gnu.org	mail exchanger = 10 eggs.gnu.org.

Authoritative answers can be found from:

$ nslookup example.com 1.1.1.1
Server:		1.1.1.1
Address:	1.1.1.1#53

Non-authoritative answer:
Name:	example.com
Address: 104.20.23.154
Name:	example.com
Address: 172.66.147.243
Name:	example.com
Address: 2606:4700:10::ac42:93f3
Name:	example.com
Address: 2606:4700:10::6814:179a

$ nslookup 8.8.8.8
8.8.8.8.in-addr.arpa	name = dns.google.

Authoritative answers can be found from:

Interactive nslookup

Without arguments, nslookup starts an interactive session with the > prompt. Settings stay in effect for the following queries.

nslookup
set type=mx
gnu.org
server 1.1.1.1
debian.org
exit

set type=mx applies to all following lookups, and server switches to another server. debian.org has three mail servers with the same preference, so mail is spread among them.

$ nslookup
> set type=mx
> gnu.org
Server:		127.0.0.53
Address:	127.0.0.53#53

Non-authoritative answer:
gnu.org	mail exchanger = 10 eggs.gnu.org.

Authoritative answers can be found from:
> server 1.1.1.1
Default server: 1.1.1.1
Address: 1.1.1.1#53
> debian.org
Server:		1.1.1.1
Address:	1.1.1.1#53

Non-authoritative answer:
debian.org	mail exchanger = 0 mailly.debian.org.
debian.org	mail exchanger = 0 muffat.debian.org.
debian.org	mail exchanger = 0 mitropoulos.debian.org.

Authoritative answers can be found from:
> exit

The host command

The host command, from the same package, gives the most compact output.

host example.com
host -t mx gnu.org
host 8.8.8.8

Without a type, host looks up the A, AAAA, and MX records, and an IP address triggers a reverse lookup. The -t option selects the type.

$ host example.com
example.com has address 104.20.23.154
example.com has address 172.66.147.243
example.com has IPv6 address 2606:4700:10::6814:179a
example.com has IPv6 address 2606:4700:10::ac42:93f3
example.com mail is handled by 0 .
$ host -t mx gnu.org
gnu.org mail is handled by 10 eggs.gnu.org.
$ host 8.8.8.8
8.8.8.8.in-addr.arpa domain name pointer dns.google.

dig, nslookup, or host

Source

dig manual page, nslookup manual page

In this article, we have used dig to query record types, specific and authoritative servers, reverse names, and to trace a resolution from the root, and we have read status codes, flags, and TTLs. We have also used nslookup, host, and getent. See also the ping and traceroute article.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Linux tutorials.