Multicast DNS (mDNS) Implementation
multicast-dns is a low-level, pure JavaScript implementation of the Multicast DNS (mDNS) protocol, widely used for zero-configuration service discovery, commonly known as Apple's Bonjour or Avahi. It facilitates device and service discovery on a local network by sending DNS queries over UDP multicast to the standard address `224.0.0.251:5353` and listening for corresponding responses. The current stable version, 7.2.5, provides an event-driven API for both querying for and responding to mDNS packets. It supports various DNS record types including A, AAAA, PTR, SRV, TXT, and HINFO, allowing applications to discover network services and resolve local hostnames. The library offers fine-grained control over network interfaces, ports, and other UDP socket options, making it a foundational component for peer-to-peer and local area network applications that require automatic service registration and discovery without relying on a central DNS server. It maintains a focus on low-level network interactions rather than abstracting into a high-level service browser.
Common errors
-
Error: bind EADDRINUSE 224.0.0.251:5353
cause Another process (e.g., a system mDNS responder like Bonjour or Avahi, or another instance of `multicast-dns`) is already listening on the default mDNS port and multicast address.fixStop the conflicting process, or configure your `multicast-dns` instance to bind to a specific `interface` if available, or a different `port` (which will prevent standard mDNS discovery for that instance). -
Error: bind EADDRNOTAVAIL
cause The specified network `interface` in the options (e.g., `interface: '192.168.0.2'`) does not exist or is not available on the current system.fixVerify the IP address configured for the `interface` option is correct and corresponds to an active network interface on your machine. Remove the `interface` option to let `multicast-dns` bind to all available interfaces (default behavior). -
TypeError: multicastdns is not a function
cause The imported/required `multicast-dns` module was not invoked as a function to create an instance. For example, `const mdns = require('multicast-dns');` instead of `const mdns = require('multicast-dns')();`.fixEnsure you are calling the imported module as a function: `const mdns = require('multicast-dns')();` for CommonJS, or `const mdns = createMdns();` after `import createMdns from 'multicast-dns';` for ESM.
Warnings
- gotcha The `reuseAddr` option for the underlying UDP socket requires Node.js version 0.11.13 or newer. Using it on older versions will result in an error or unexpected behavior.
- gotcha The mDNS protocol operates over UDP port 5353, which is a well-known port. Firewalls or other services (like Bonjour/Avahi daemons) might block access or already be using this port, leading to `EADDRINUSE` or `EACCES` errors when binding the socket.
- gotcha The README and examples primarily demonstrate CommonJS (`require()`) usage. While modern Node.js supports ESM, careful consideration is needed for `import` statements, especially when the package exports a factory function that needs to be invoked immediately.
Install
-
npm install multicast-dns -
yarn add multicast-dns -
pnpm add multicast-dns
Imports
- mdns instance (CommonJS)
const mdns = require('multicast-dns');const mdns = require('multicast-dns')(); - mdns instance (ESM)
import { mdns } from 'multicast-dns';import createMdns from 'multicast-dns'; const mdns = createMdns();
- Packet Types (TypeScript)
import { Packet } from 'multicast-dns';import type { Packet, Question, Answer } from 'multicast-dns';
Quickstart
import createMdns from 'multicast-dns';
const mdns = createMdns();
mdns.on('response', function(response) {
console.log('Got a mDNS response packet:', JSON.stringify(response, null, 2));
});
mdns.on('query', function(query) {
console.log('Got a mDNS query packet:', JSON.stringify(query, null, 2));
// Example: Respond to a query for 'my-service.local'
if (query.questions[0] && query.questions[0].name === 'my-service.local') {
mdns.respond({
answers: [{
name: 'my-service.local',
type: 'A',
ttl: 120,
data: '127.0.0.1' // Replace with actual IP
}]
});
console.log('Responded to query for my-service.local');
}
});
// Query for an A record for a local hostname (e.g., your-hostname.local)
mdns.query({
questions:[
{
name: 'your-hostname.local',
type: 'A'
},
{
name: 'my-service.local',
type: 'SRV'
}
]
});
console.log('Sent mDNS query for your-hostname.local and my-service.local');
// Destroy the instance after a timeout to prevent resource leaks in short-lived scripts
setTimeout(() => {
mdns.destroy();
console.log('mDNS instance destroyed.');
}, 10000);