The dns module provides DNS resolution and lookup capabilities. Here's how to use it effectively.
Basic Lookups#
1const dns = require('dns');
2const { promisify } = require('util');
3
4// Callback-based lookup
5dns.lookup('google.com', (err, address, family) => {
6 if (err) {
7 console.error(err);
8 return;
9 }
10 console.log(`Address: ${address}, Family: IPv${family}`);
11});
12
13// Promise-based lookup
14const lookupAsync = promisify(dns.lookup);
15
16async function lookup(hostname) {
17 try {
18 const { address, family } = await lookupAsync(hostname);
19 console.log(`Address: ${address}, Family: IPv${family}`);
20 return address;
21 } catch (err) {
22 console.error(`Lookup failed: ${err.message}`);
23 throw err;
24 }
25}
26
27// Using dns.promises (Node.js 10.6+)
28const dnsPromises = require('dns').promises;
29
30async function lookupModern(hostname) {
31 const result = await dnsPromises.lookup(hostname);
32 return result.address;
33}IP Version Options#
1const dns = require('dns').promises;
2
3// Get IPv4 address
4async function getIPv4(hostname) {
5 const { address } = await dns.lookup(hostname, { family: 4 });
6 return address;
7}
8
9// Get IPv6 address
10async function getIPv6(hostname) {
11 const { address } = await dns.lookup(hostname, { family: 6 });
12 return address;
13}
14
15// Get all addresses
16async function getAllAddresses(hostname) {
17 const addresses = await dns.lookup(hostname, { all: true });
18 return addresses;
19 // [{ address: '172.217.14.110', family: 4 }, ...]
20}
21
22// With hints
23async function lookupWithHints(hostname) {
24 const { address } = await dns.lookup(hostname, {
25 hints: dns.ADDRCONFIG | dns.V4MAPPED,
26 });
27 return address;
28}DNS Resolution#
1const dns = require('dns').promises;
2
3// Resolve A records (IPv4)
4async function resolveA(hostname) {
5 const addresses = await dns.resolve4(hostname);
6 return addresses; // ['172.217.14.110', ...]
7}
8
9// Resolve AAAA records (IPv6)
10async function resolveAAAA(hostname) {
11 const addresses = await dns.resolve6(hostname);
12 return addresses;
13}
14
15// Resolve MX records (mail)
16async function resolveMX(hostname) {
17 const records = await dns.resolveMx(hostname);
18 return records;
19 // [{ priority: 10, exchange: 'mail.example.com' }, ...]
20}
21
22// Resolve TXT records
23async function resolveTXT(hostname) {
24 const records = await dns.resolveTxt(hostname);
25 return records;
26 // [['v=spf1 include:_spf.google.com ~all'], ...]
27}
28
29// Resolve CNAME records
30async function resolveCNAME(hostname) {
31 const records = await dns.resolveCname(hostname);
32 return records; // ['www.example.com']
33}
34
35// Resolve NS records (name servers)
36async function resolveNS(hostname) {
37 const records = await dns.resolveNs(hostname);
38 return records; // ['ns1.example.com', 'ns2.example.com']
39}
40
41// Resolve SOA record (Start of Authority)
42async function resolveSOA(hostname) {
43 const record = await dns.resolveSoa(hostname);
44 return record;
45 // { nsname, hostmaster, serial, refresh, retry, expire, minttl }
46}
47
48// Resolve SRV records
49async function resolveSRV(hostname) {
50 const records = await dns.resolveSrv(hostname);
51 return records;
52 // [{ priority, weight, port, name }, ...]
53}Generic Resolution#
1const dns = require('dns').promises;
2
3// Resolve any record type
4async function resolveAny(hostname) {
5 const records = await dns.resolveAny(hostname);
6 return records;
7 // Mixed array of all record types
8}
9
10// Resolve specific type
11async function resolve(hostname, recordType) {
12 const records = await dns.resolve(hostname, recordType);
13 return records;
14}
15
16// Usage
17await resolve('example.com', 'A');
18await resolve('example.com', 'MX');
19await resolve('example.com', 'TXT');
20
21// Available record types:
22// 'A', 'AAAA', 'ANY', 'CAA', 'CNAME', 'MX', 'NAPTR',
23// 'NS', 'PTR', 'SOA', 'SRV', 'TXT'Reverse DNS Lookup#
1const dns = require('dns').promises;
2
3// IP to hostname
4async function reverseLookup(ip) {
5 try {
6 const hostnames = await dns.reverse(ip);
7 return hostnames; // ['hostname.example.com']
8 } catch (err) {
9 if (err.code === 'ENOTFOUND') {
10 return null; // No reverse DNS entry
11 }
12 throw err;
13 }
14}
15
16// Get PTR records
17async function resolvePTR(ip) {
18 const records = await dns.resolvePtr(ip);
19 return records;
20}Custom DNS Servers#
1const dns = require('dns');
2const { Resolver } = dns;
3
4// Create resolver with custom servers
5const resolver = new Resolver();
6resolver.setServers(['8.8.8.8', '8.8.4.4']); // Google DNS
7
8// Use custom resolver
9resolver.resolve4('example.com', (err, addresses) => {
10 console.log(addresses);
11});
12
13// Promise-based custom resolver
14const { promisify } = require('util');
15const resolve4Async = promisify(resolver.resolve4.bind(resolver));
16
17async function resolveWithGoogle(hostname) {
18 return resolve4Async(hostname);
19}
20
21// Get current DNS servers
22console.log(dns.getServers());
23// ['192.168.1.1', '8.8.8.8']
24
25// Set default servers
26dns.setServers(['1.1.1.1', '1.0.0.1']); // Cloudflare DNSError Handling#
1const dns = require('dns').promises;
2
3async function safeLookup(hostname) {
4 try {
5 const result = await dns.lookup(hostname);
6 return { success: true, ...result };
7 } catch (err) {
8 return {
9 success: false,
10 code: err.code,
11 message: getErrorMessage(err.code),
12 };
13 }
14}
15
16function getErrorMessage(code) {
17 const messages = {
18 ENODATA: 'DNS server returned answer with no data',
19 EFORMERR: 'DNS server claims query was misformatted',
20 ESERVFAIL: 'DNS server returned general failure',
21 ENOTFOUND: 'Domain name not found',
22 ENOTIMP: 'DNS server does not implement requested operation',
23 EREFUSED: 'DNS server refused query',
24 EBADQUERY: 'Misformatted DNS query',
25 EBADNAME: 'Misformatted hostname',
26 EBADFAMILY: 'Unsupported address family',
27 EBADRESP: 'Misformatted DNS reply',
28 ECONNREFUSED: 'Could not contact DNS servers',
29 ETIMEOUT: 'Timeout while contacting DNS servers',
30 EOF: 'End of file',
31 EFILE: 'Error reading file',
32 ENOMEM: 'Out of memory',
33 EDESTRUCTION: 'Channel is being destroyed',
34 EBADSTR: 'Misformatted string',
35 EBADFLAGS: 'Illegal flags specified',
36 ENONAME: 'Given hostname is not numeric',
37 EBADHINTS: 'Illegal hints flags specified',
38 ENOTINITIALIZED: 'c-ares library initialization not yet performed',
39 ELOADIPHLPAPI: 'Error loading iphlpapi.dll',
40 EADDRGETNETWORKPARAMS: 'Could not find GetNetworkParams function',
41 ECANCELLED: 'DNS query cancelled',
42 };
43 return messages[code] || 'Unknown DNS error';
44}Caching DNS Results#
1const dns = require('dns').promises;
2
3class DNSCache {
4 constructor(ttl = 60000) {
5 this.cache = new Map();
6 this.ttl = ttl;
7 }
8
9 async lookup(hostname, options = {}) {
10 const key = `${hostname}:${options.family || 'any'}`;
11 const cached = this.cache.get(key);
12
13 if (cached && Date.now() < cached.expires) {
14 return cached.result;
15 }
16
17 const result = await dns.lookup(hostname, options);
18 this.cache.set(key, {
19 result,
20 expires: Date.now() + this.ttl,
21 });
22
23 return result;
24 }
25
26 async resolve(hostname, recordType = 'A') {
27 const key = `${hostname}:${recordType}`;
28 const cached = this.cache.get(key);
29
30 if (cached && Date.now() < cached.expires) {
31 return cached.result;
32 }
33
34 const result = await dns.resolve(hostname, recordType);
35 this.cache.set(key, {
36 result,
37 expires: Date.now() + this.ttl,
38 });
39
40 return result;
41 }
42
43 clear() {
44 this.cache.clear();
45 }
46}
47
48// Usage
49const dnsCache = new DNSCache(300000); // 5 minute TTL
50
51async function lookupCached(hostname) {
52 return dnsCache.lookup(hostname);
53}Practical Examples#
1const dns = require('dns').promises;
2
3// Validate email domain
4async function validateEmailDomain(email) {
5 const domain = email.split('@')[1];
6 if (!domain) return false;
7
8 try {
9 const mxRecords = await dns.resolveMx(domain);
10 return mxRecords.length > 0;
11 } catch {
12 return false;
13 }
14}
15
16// Check domain availability
17async function isDomainAvailable(domain) {
18 try {
19 await dns.lookup(domain);
20 return false; // Domain resolves, not available
21 } catch (err) {
22 if (err.code === 'ENOTFOUND') {
23 return true; // Domain doesn't resolve, might be available
24 }
25 throw err;
26 }
27}
28
29// Get all DNS info for domain
30async function getDomainInfo(domain) {
31 const info = {
32 domain,
33 addresses: [],
34 mx: [],
35 ns: [],
36 txt: [],
37 soa: null,
38 };
39
40 try {
41 info.addresses = await dns.resolve4(domain);
42 } catch {}
43
44 try {
45 info.mx = await dns.resolveMx(domain);
46 } catch {}
47
48 try {
49 info.ns = await dns.resolveNs(domain);
50 } catch {}
51
52 try {
53 info.txt = await dns.resolveTxt(domain);
54 } catch {}
55
56 try {
57 info.soa = await dns.resolveSoa(domain);
58 } catch {}
59
60 return info;
61}
62
63// Health check with DNS
64async function checkDNSHealth(servers) {
65 const results = await Promise.all(
66 servers.map(async (server) => {
67 const resolver = new dns.Resolver();
68 resolver.setServers([server]);
69
70 const start = Date.now();
71 try {
72 await resolver.resolve4('google.com');
73 return {
74 server,
75 status: 'healthy',
76 latency: Date.now() - start,
77 };
78 } catch (err) {
79 return {
80 server,
81 status: 'unhealthy',
82 error: err.message,
83 };
84 }
85 })
86 );
87
88 return results;
89}Best Practices#
Usage:
✓ Use dns.promises for async/await
✓ Handle all error codes appropriately
✓ Implement caching for repeated lookups
✓ Use custom resolvers when needed
Performance:
✓ Cache DNS results with appropriate TTL
✓ Use parallel resolution when possible
✓ Consider using faster DNS servers
✓ Implement timeouts
Security:
✓ Validate hostnames before lookup
✓ Use DNSSEC when available
✓ Be aware of DNS rebinding attacks
✓ Log suspicious DNS queries
Avoid:
✗ Blocking the event loop with sync calls
✗ Ignoring DNS errors
✗ Hardcoding DNS servers in production
✗ Making DNS calls in hot paths
Conclusion#
The dns module provides comprehensive DNS functionality for Node.js. Use dns.promises for modern async/await code, implement caching for performance, and handle errors appropriately. Consider using custom resolvers for specialized DNS requirements.