Looking up Apple Devices in a Local Network

Article's main picture
  • #macOS

• 7 min read


A local area network (LAN) is a computer network that interconnects computers within a limited area. Ethernet and Wi-Fi are the two most common technologies for local area networks. Each workstation in the network has its own internet protocol (IP) address, so these addresses can be utilized to distinguish devices in the network.

Address resolution protocol

The easiest way to scan the local network to detect which IP addresses are already taken is to use the address resolution protocol, ARP, which maps local IP addresses to the physical MAC addresses of devices.

On macOS, there is a command-line utility called arp:

arp -a

It gives the mapping table which shows local IP address assignations to physical MAC addresses.

Example result:

$ arp -a
? ( at ff:ff:ff:ff:ff:ff on en0 ifscope [ethernet]
? ( at 4c:32:75:c3:3:ce on en0 ifscope [ethernet]
? ( at (incomplete) on en0 ifscope [ethernet]
? ( at 3c:22:fb:19:8e:20 on en0 ifscope [ethernet]
? ( at 58:d3:49:5a:53:c2 on en0 ifscope [ethernet]
? ( at 18:3e:ef:e6:8b:a6 on en0 ifscope [ethernet]
? ( at (incomplete) on en0 ifscope [ethernet]
? ( at ac:bc:32:5d:27:5 on en0 ifscope [ethernet]
? ( at (incomplete) on en0 ifscope [ethernet]
? ( at 60:5b:b4:8e:f0:f3 on en0 ifscope [ethernet]
? ( at 26:58:32:f4:c:d6 on en0 ifscope [ethernet]
? ( at d4:90:9c:e6:d4:f5 on en0 ifscope [ethernet]
? ( at (incomplete) on en0 ifscope [ethernet]
? ( at (incomplete) on en0 ifscope [ethernet]
? ( at f8:4d:89:7f:d7:2f on en0 ifscope permanent [ethernet]
? ( at 50:ec:50:4:b:e7 on en0 ifscope [ethernet]

Note: the arp tool is open sourced.

MAC address

At the point when we have the MAC addresses list, we can look up the device's manufacturer.

A MAC Address is a 12-digit hexadecimal number (6-Byte binary number), most often written in the colon-hexadecimal notation. The first 6 digits (say 00:40:96) of a MAC address identify the manufacturer and constitute the organizational unique identifier or OUI. IEEE Registration Authority Committee assigns these MAC prefixes to its registered vendors.

Apple's OUI Examples:


However, even if we have a device manufacturer, we still can't get the device type and model. Some interprocess communication should be done on top to discover device information.


One of the widely used technologies for networking and discoverability is Bonjour from Apple.

Bonjour, also known as zero-configuration networking, enables the automatic discovery of devices and services on a local network using industry-standard IP protocols. Bonjour makes it easy to discover, publish, and resolve network services with a sophisticated, easy-to-use programming interface that is accessible from Cocoa, Ruby, Python, and other languages.

Apple devices publish corresponding Bonjour services to the network so that others can discover and distinguish them by service type. Bonjour locates devices such as printers, and other computers, and the services that those devices offer on a local network using multicast Domain Name System (mDNS) service records.


We will implement a prototype in Swift because Foundation has a top-level API for discovering and monitoring Bonjour services. This API collection is deprecated but is still suitable for demonstrating purposes and is backward compatible.

One can achieve the same result using the new Network framework.

For the prototype, we will use the following pattern:

  1. Browse for the determined list of the services to set up the devices list.
  2. Monitor informational device services for TXT records updates.

Browse needed services

For our purposes, we will set up service discovery of several types: _companion-link._tcp, _rdlink._tcp., _airport._tcp..


Companion Link is an undocumented Apple service for communication between Apple devices; however, almost all devices tested are discoverable by it.


Remote Active Queue Management service. Used for iOS devices discovering and distinguishing.


Admin Airport Utility service. Used for discovering Airport Base Stations.

Once we have several services to discover, we need to have an array of NetServiceBrowser:

let servicesToBrowse = ["_companion-link._tcp.", "_rdlink._tcp.", "_airport._tcp."]

servicesToBrowse.forEach {
    let browser = NetServiceBrowser()
    browser.delegate = self
    browser.searchForServices(ofType: $0, inDomain: "local.")

NetServiceBrowserDelegate delegate methods will be invoked in case of services discovered:

func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
    .map { type -> NetService in
        let service = NetService(domain: "local.", type: type, name: service.name)
        service.delegate = self
        return service
    }.forEach {

In the function above we start monitoring the discovered services to get their TXT records. We use several services type there:

"_device-info._tcp.", "_airplay._tcp."


Device Info Service. Returns basic device information with TXT record.


Airplay Info Service. Returns basic device information with TXT record. Used for AirPlay-based devices, like HomePods.

NetServiceDelegate delegate methods will be invoked in case of TXT records updated:

func netService(_ sender: NetService, didUpdateTXTRecord data: Data) {
    guard let deviceModel = self.extractModelFromTXTRecord(recordData: data) else {
    if let existingDevice = self.devices.first(where: { $0.serviceName == sender.name }) {
        existingDevice.updateWithDeviceModel(model: deviceModel)
    } else {
        let device = Device(serviceName: sender.name, model: deviceModel)

private func extractModelFromTXTRecord(recordData: Data) -> String? {
    let txtDictionary = NetService.dictionary(fromTXTRecord: recordData)
    //Check for other keys here
    guard let modelData = txtDictionary["model"], let model = String(data: modelData, encoding: .utf8) else {
        return nil
    return model

TXT dictionaries from above contain the "model" key, corresponding to the device model in the value. For example, MacBookPro18,3 for MacBook Pro (14-inch, 2021) or j210ap for iPad mini (5th generation). Public "model to marketing names" databases could be used here to get human-readable names, or we could also use the private Launch Services function.

Launch Services device type identifier

Launch Services framework provides a private function to translate a device model into a device type identifier to use it with public NSWorkspace API to get marketing titles and images.

extern NSString* _LSCreateDeviceTypeIdentifierWithModelCode(NSString *);

@implementation ANLaunchService

+ (NSString *)deviceTypeIdentifierFromModelCode:(NSString *)modelCode
    return _LSCreateDeviceTypeIdentifierWithModelCode(modelCode);



let workspace = NSWorkspace.shared
let typeIdentifier = ANLaunchService.deviceTypeIdentifier(fromModelCode: model)
let deviceDescription = workspace.localizedDescription(forType: typeIdentifier) ?? ""
let deviceIcon = workspace.icon(forFileType: typeIdentifier)

With the combination of the above APIs, we get the complete list of available Apple devices in a local network, along with their device types and marketing information.

Available Apple devices in a local network. AirPort, Apple TV, HomePod, MacBook Pro, and iPhone are trademarks of Apple Inc.
Available Apple devices in a local network. AirPort, Apple TV, HomePod, MacBook Pro, and iPhone are trademarks of Apple Inc.


With the given set of available macOS APIs, it is possible to build a fully functional list of Apple devices in the local network.

Potential integrations

Knowledge of the local network environment can be beneficial for building appropriate advertisement targeting. It can also provide possibilities for monitoring local network devices for further manipulation. We could examine and use the local network to suggest software installation to specific workstations with appropriate hardware.

This is an independent publication and it has not been authorized, sponsored, or otherwise approved by Apple Inc.

More From research

Subscribe to our newsletter