@devioarts/capacitor-mdns
mDNS plugin for Capacitor that supports Bonjour/mDNS advertisements and discovery on iOS, Android, Electron, and a safe web fallback.
Supported Capacitor version: v8. iOS 15 or later is required.
Supported platforms: ✓ iOS ✓ Android ✓ Electron ✓ Web fallback
The in-repository playground is the example app used during development.
Install
npm install @devioarts/capacitor-mdns
npx cap sync
For Electron, also install bonjour-service@~1.4.0 and run npx cap-electron sync.
See the Electron setup for details.
Upgrading from 0.1.0
Version 0.2.0 retains the existing method signatures and result shapes and adds continuous discovery. It also tightens input validation, changes overlapping discovery and error handling, and raises the declared iOS minimum to 15.0. Review the upgrade notes before updating an existing application.
Usage
import { mDNS } from '@devioarts/capacitor-mdns';
const runtime = await mDNS.getPluginPlatform();
await mDNS.startBroadcast({ type: '_http._tcp.', name: 'MyService', port: 9100 });
const result = await mDNS.discover({ type: '_http._tcp.', timeout: 3000 });
await mDNS.stopBroadcast();
Continuous discovery
Thank you, Idrimi, for contributing the original continuous discovery feature in PR #7.
watchServices() monitors multiple service types on iOS, Android and Electron until stopped.
Register listeners before starting; a new valid call replaces the previous watch.
const found = await mDNS.addListener('serviceFound', ({ service }) => {
console.log('Found', service.name, service.hosts, service.port);
});
const lost = await mDNS.addListener('serviceLost', ({ service }) => {
console.log('Lost', service.name, service.hosts, service.port);
});
const errors = await mDNS.addListener('watchError', (event) => {
console.error(event.type, event.errorMessage, event.watching);
});
const result = await mDNS.watchServices({
types: ['_http._tcp.', '_airplay._tcp.', '_googlecast._tcp.'],
});
// Later, including when leaving the screen:
await mDNS.stopWatching();
await Promise.all([found.remove(), lost.remove(), errors.remove()]);
Found/lost events contain the full service snapshot; hosts is always an array. A service
that disappears before resolving emits neither event. Browser errors stop watching and emit
watchError with watching: false; exhausted resolution retries emit it with watching: true.
stopWatching() leaves broadcasting and one-shot discovery running. Browsers do not support mDNS.
Platform Setup
Android requires mDNS/network permissions in AndroidManifest.xml; the plugin also declares them
so they are merged during sync. iOS requires local network keys in Info.plist.
Electron support is intended for devioarts/capacitor-electron
and uses metadata exported from @devioarts/capacitor-mdns/electron/settings.
Detailed setup lives in:
API
getPluginPlatform()startBroadcast(...)stopBroadcast()discover(...)watchServices(...)stopWatching()addListener('serviceFound' | 'serviceLost', ...)addListener('watchError', ...)removeAllListeners()- Interfaces
- Type Aliases
Public API surface of the Capacitor mDNS plugin.
getPluginPlatform()
getPluginPlatform() => Promise<MdnsPluginPlatformResult>
Return the platform implementation currently serving plugin calls.
Returns: Promise<MdnsPluginPlatformResult>
startBroadcast(...)
startBroadcast(options: MdnsBroadcastOptions) => Promise<MdnsBroadcastResult>
Start advertising a Bonjour/mDNS service.
| Param | Type | Description |
|---|---|---|
options | MdnsBroadcastOptions | - {@link MdnsBroadcastOptions} |
Returns: Promise<MdnsBroadcastResult>
stopBroadcast()
stopBroadcast() => Promise<MdnsStopResult>
Stop advertising the currently registered service (no-op if none).
Returns: Promise<MdnsStopResult>
discover(...)
discover(options?: MdnsDiscoverOptions | undefined) => Promise<MdnsDiscoverResult>
Discover services of a given type and optionally filter by instance name.
| Param | Type | Description |
|---|---|---|
options | MdnsDiscoverOptions | - {@link MdnsDiscoverOptions} |
Returns: Promise<MdnsDiscoverResult>
watchServices(...)
watchServices(options: MdnsWatchOptions) => Promise<MdnsWatchResult>
Continuously watch several service types. A valid call replaces the previous watch.
Register listeners before starting. Each resolved service emits serviceFound once;
disappearance emits serviceLost with its last snapshot. No loss is emitted for an
unresolved service. Watching and one-shot discovery can run together.
Thanks to Idrimi for contributing the original continuous discovery feature (PR #7).
| Param | Type |
|---|---|
options | MdnsWatchOptions |
Returns: Promise<MdnsWatchResult>
stopWatching()
stopWatching() => Promise<MdnsWatchStopResult>
Stop all watchers. No events from that watch are emitted after this resolves.
Returns: Promise<MdnsWatchStopResult>
addListener('serviceFound' | 'serviceLost', ...)
addListener(eventName: 'serviceFound' | 'serviceLost', handler: (event: MdnsServiceEvent) => void) => Promise<PluginListenerHandle>
| Param | Type |
|---|---|
eventName | 'serviceFound' | 'serviceLost' |
handler | (event: MdnsServiceEvent) => void |
Returns: Promise<PluginListenerHandle>
addListener('watchError', ...)
addListener(eventName: 'watchError', handler: (event: MdnsWatchErrorEvent) => void) => Promise<PluginListenerHandle>
| Param | Type |
|---|---|
eventName | 'watchError' |
handler | (event: MdnsWatchErrorEvent) => void |
Returns: Promise<PluginListenerHandle>
removeAllListeners()
removeAllListeners() => Promise<void>
Interfaces
MdnsPluginPlatformResult
Result of getPluginPlatform(). Useful for validating that calls are routed through the expected platform bridge.
| Prop | Type | Description |
|---|---|---|
platform | MdnsPluginPlatform | Platform implementation that produced this result. |
MdnsBroadcastResult
Result of startBroadcast(). Indicates whether advertising is active
and the final service name. On failure, error is true and errorMessage
describes the issue.
| Prop | Type | Description |
|---|---|---|
error | boolean | True if the operation failed. |
errorMessage | string | null | Error description or null on success. |
name | string | Final (possibly uniquified) service instance name. Empty on failure. |
publishing | boolean | Whether an advertiser is active, or may still be active after failed cleanup. |
MdnsBroadcastOptions
Options for starting a Bonjour/mDNS advertisement.
| Prop | Type | Description |
|---|---|---|
type | string | Service type (including the trailing dot). |
name | string | Service instance name (maximum 63 UTF-8 bytes). Defaults to DevIOArtsMDNS. |
port | number | TCP port to advertise. |
txt | MdnsTxt | Optional TXT key–value pairs (UTF-8 strings). |
MdnsStopResult
Result of stopBroadcast(). Indicates whether the advertiser is active after the call (normally false) and includes error information.
| Prop | Type | Description |
|---|---|---|
error | boolean | True if an error occurred while stopping. |
errorMessage | string | null | Error description or null on success. |
publishing | boolean | False after confirmed stop; true when stopping failed and the advertiser may still be active. |
MdnsDiscoverResult
Result of discover(). Contains normalized services and error information.
| Prop | Type | Description |
|---|---|---|
error | boolean | True if discovery encountered an error (partial results may still be present). |
errorMessage | string | null | Error description or null when no error occurred. |
servicesFound | number | Convenience count equal to services.length. |
services | MdnsService[] | Resolved services with numeric addresses. Empty on error; partial results are discarded. |
MdnsService
Normalized description of a discovered Bonjour/mDNS service. Returned from {@link mDNSPlugin.discover}.
| Prop | Type | Description |
|---|---|---|
name | string | Instance name of the service (may be uniqued by the OS, e.g. "My App (2)"). |
type | string | Full service type including the trailing dot, e.g. "_http._tcp.". |
domain | string | Service domain; typically "local.". |
port | number | Port the service advertises. |
hosts | string[] | Resolved numeric IP addresses, IPv4 first, then IPv6 with any available scope suffix. |
hostname | string | Host name when supplied by the platform, e.g. "my-device.local.". |
txt | MdnsTxt | TXT dictionary (key → value). |
MdnsDiscoverOptions
Options for Bonjour/mDNS discovery.
| Prop | Type | Description |
|---|---|---|
type | string | Service type (including the trailing dot). |
name | string | Optional instance name filter (prefix-safe). |
timeout | number | Discovery timeout in milliseconds. Finite numbers only; fractions are truncated and the delay is clamped to 0–2147483647. |
useNW | boolean | iOS-only hint to use NWBrowser instead of NetServiceBrowser. |
MdnsWatchResult
Native browsers have been requested; later failures are reported through watchError.
| Prop | Type |
|---|---|
error | boolean |
errorMessage | string | null |
watchersStarted | number |
MdnsWatchOptions
Options for continuous discovery on iOS, Android and Electron.
| Prop | Type | Description |
|---|---|---|
types | string[] | Nonempty list of service types. Trailing dots are optional; duplicates are merged. |
MdnsWatchStopResult
Stops watching independently of any active broadcast.
| Prop | Type |
|---|---|
error | boolean |
errorMessage | string | null |
watching | boolean |
PluginListenerHandle
| Prop | Type |
|---|---|
remove | () => Promise<void> |
MdnsServiceEvent
Both found and lost events contain a complete service snapshot, including hosts.
| Prop | Type |
|---|---|
service | MdnsService |
MdnsWatchErrorEvent
Browser failures stop the watch; exhausted service resolution retries leave it running.
| Prop | Type |
|---|---|
type | string |
errorMessage | string |
watching | boolean |
Type Aliases
MdnsPluginPlatform
Runtime implementation that handled a plugin call.
'ios' | 'android' | 'electron' | 'web'
MdnsTxt
Key–value map for TXT records of a Bonjour/mDNS service. Values are UTF-8 strings; binary payloads are not supported by this API.
Record<string, string>
Record
Construct a type with a set of properties K of type T
{
[P in K]: T;
}