A domain name like example.com is easy for humans to remember and completely meaningless to the actual network hardware moving your data — that hardware needs an IP address. DNS is the system that translates one into the other, and Node.js's dns module lets your code perform that lookup directly.
A basic lookup
const dns = require('dns');
dns.lookup('example.com', (err, address, family) => {
if (err) return console.error(err);
console.log(`Address: ${address} (IPv${family})`);
});
dns.lookup() uses your operating system's own resolution mechanism (the same one used when you type a URL into a browser), including any local hosts file entries and OS-level caching.
Resolving specific record types
For lower-level control, and to bypass OS-level caching in favor of asking DNS servers directly, resolve() and its variants are used instead:
dns.resolve4('example.com', (err, addresses) => {
if (err) return console.error(err);
console.log('IPv4 addresses:', addresses); // returns an array — a domain can have several
});
dns.resolveMx('example.com', (err, records) => {
if (err) return console.error(err);
console.log('Mail servers:', records); // useful when validating an email domain can actually receive mail
});
Reverse lookup — going from an IP back to a hostname
dns.reverse('93.184.216.34', (err, hostnames) => {
if (err) return console.error(err);
console.log('Hostnames:', hostnames);
});
A practical use case: verifying an email domain during signup
const dns = require('dns');
function isDomainReachable(email) {
const domain = email.split('@')[1];
return new Promise((resolve) => {
dns.resolveMx(domain, (err, records) => {
resolve(!err && records && records.length > 0);
});
});
}
isDomainReachable('someone@example.com').then((reachable) => {
console.log(reachable ? 'Domain can receive mail' : 'Domain looks invalid or has no mail server');
});
This catches an obviously wrong or nonexistent domain early, before actually attempting to send an email there and finding out it bounces.
Using Promises instead of callbacks
const dnsPromises = require('dns/promises');
async function checkDomain(domain) {
const addresses = await dnsPromises.resolve4(domain);
console.log(addresses);
}
When you'd actually reach for this module
Most applications never call dns directly — the networking code you already write (an outgoing http request, a database connection using a hostname) resolves domain names automatically behind the scenes. Reaching for dns explicitly tends to happen for specific validation logic (checking a domain is real before storing it), diagnostic tooling, or custom load-balancing logic that needs to inspect DNS records itself.