{"id":12768,"library":"bonjour-service","title":"Bonjour/Zeroconf Service Discovery for Node.js","description":"bonjour-service is a TypeScript implementation of the Bonjour/Zeroconf protocol, enabling service publishing and discovery on local networks using multicast DNS. It functions as a modern rewrite of the popular `watson/bonjour` package, bringing contemporary TypeScript practices and improved maintainability. Currently stable at version 1.3.0, the package sees periodic updates, often including dependency bumps and minor feature enhancements, as indicated by recent changelogs. Its primary differentiator is providing a reliable, actively maintained, and type-safe solution for mDNS/DNS-SD within the Node.js ecosystem, suitable for applications requiring local network service announcement and detection, such as IoT devices or local development tooling. It offers functionalities to advertise services (e.g., HTTP servers) and browse for existing ones, handling the underlying UDP socket communication and DNS packet parsing.","status":"active","version":"1.3.0","language":"javascript","source_language":"en","source_url":"https://github.com/onlxltd/bonjour-service","tags":["javascript","bonjour","zeroconf","zero","configuration","mdns","dns","service","discovery","typescript"],"install":[{"cmd":"npm install bonjour-service","lang":"bash","label":"npm"},{"cmd":"yarn add bonjour-service","lang":"bash","label":"yarn"},{"cmd":"pnpm add bonjour-service","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for underlying mDNS server functionality.","package":"multicast-dns","optional":false},{"reason":"Used for parsing and constructing DNS TXT records.","package":"dns-txt","optional":false}],"imports":[{"note":"The library is primarily designed for ESM with TypeScript. While CommonJS `require` might work in some environments, `import` is the idiomatic and fully supported way.","wrong":"const Bonjour = require('bonjour-service')","symbol":"Bonjour","correct":"import { Bonjour } from 'bonjour-service'"},{"note":"When importing types for type annotations, use `import type` to ensure it's not bundled as a runtime import, especially critical for tree-shaking and avoiding issues in strict ESM setups.","wrong":"import { Service } from 'bonjour-service'","symbol":"Service","correct":"import type { Service } from 'bonjour-service'"},{"note":"Type for the constructor options, useful for strict TypeScript environments.","symbol":"Options","correct":"import type { BonjourOptions } from 'bonjour-service'"}],"quickstart":{"code":"import { Bonjour } from 'bonjour-service';\nimport { createServer } from 'http';\n\nconst bonjour = new Bonjour();\nconst server = createServer((req, res) => {\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  res.end('Hello from bonjour-service!');\n});\n\nconst port = 3000;\nserver.listen(port, () => {\n  console.log(`HTTP server listening on port ${port}`);\n  // Advertise an HTTP server on port 3000\n  const publishedService = bonjour.publish({\n    name: 'My bonjour-service Web Server',\n    type: 'http',\n    port: port,\n    txt: { version: '1.0', path: '/' }\n  });\n  publishedService.on('up', () => {\n    console.log(`Service '${publishedService.name}' published successfully.`);\n  });\n\n  // Browse for all http services\n  const browser = bonjour.find({ type: 'http' });\n  browser.on('up', (service) => {\n    console.log('Found an HTTP server:', service.name, service.port, service.host);\n  });\n\n  // Stop browsing and unpublish after a delay\n  setTimeout(() => {\n    console.log('Stopping services...');\n    browser.stop();\n    publishedService.stop();\n    bonjour.destroy();\n    server.close(() => console.log('HTTP server closed.'));\n  }, 15000);\n});\n","lang":"typescript","description":"This quickstart demonstrates how to publish an HTTP service and simultaneously discover other HTTP services on the local network using `bonjour-service`."},"warnings":[{"fix":"Adjust firewall settings to allow UDP traffic on port 5353 for the Node.js process. On Linux, consider `sudo ufw allow 5353/udp`.","message":"Firewall rules can prevent `bonjour-service` from functioning correctly, as it relies on multicast UDP on port 5353. Ensure this port is open for both inbound and outbound traffic if services are not being discovered or published.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Initialize Bonjour with an error callback: `const bonjour = new Bonjour({}, (err) => console.error('Bonjour error:', err));`","message":"The `Bonjour` constructor can optionally take an `errorCallback` to handle errors gracefully that would otherwise crash the process, particularly issues with the underlying `multicast-dns` server. It is highly recommended to provide this callback.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Dynamically generate or append a unique identifier (e.g., hostname, UUID) to service names, especially in environments where multiple instances of the same service might run concurrently.","message":"When publishing services, ensure the `name` is unique on the network for a given `type` and `protocol` to avoid conflicts. Duplicate service names can lead to unpredictable behavior or services not being properly advertised.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always call `bonjour.destroy()` when your application is shutting down or no longer needs service discovery/publishing. For individual services/browsers, use `service.stop()` and `browser.stop()`.","message":"The `destroy()` method is crucial for releasing network resources. Failing to call `destroy()` on the `Bonjour` instance (and `stop()` on individual services/browsers) can leave UDP sockets open, leading to resource leaks or preventing process exit.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure only one instance of `bonjour-service` (or any other mDNS client/server) is running at a time. If running multiple, ensure each `Bonjour` instance has its own unique port configuration if necessary, though mDNS typically operates on 5353. For system-wide conflicts, identify and stop the conflicting process.","cause":"Another process is already using the mDNS port (5353). This is common if another mDNS client or server is running.","error":"Error: bind EADDRINUSE 0.0.0.0:5353"},{"fix":"This is often transient. Ensure the target device is online and accessible on the local network. Implement retries or a more robust service tracking logic in your application to handle temporary resolution failures.","cause":"When browsing for services, the `host` property might sometimes appear as 'no such host' if the mDNS resolver couldn't immediately resolve the hostname from the IP address, or if the host went offline before a full resolution could occur.","error":"Error: no such host"},{"fix":"If using CommonJS, try `const { Bonjour } = require('bonjour-service');`. If using ES modules, ensure your environment supports `import` syntax and you are using `import { Bonjour } from 'bonjour-service';`.","cause":"Attempting to use `require()` with an ES module or incorrect destructuring in CommonJS.","error":"TypeError: Bonjour is not a constructor"}],"ecosystem":"npm"}