[ACCEPTED]-Query ARP cache to get MAC ID-networking

Accepted answer
Score: 11

Java provides no direct way to query the 14 MAC address of a host in your network, as 13 this is abstracted away by Java's socket 12 libraries.

In a way, this makes sense, because 11 the MAC address of a host actually says 10 very little. There is no such thing as "the" MAC 9 address of a host.

  • Many hosts will have several NICs, all with a separate MAC address, with which they can connect to the network. The computer I'm on at the moment has a wired ethernet adapter, a WiFi adapter, and a Firewire adapter, and they all have their own MAC address. This means that there is no definitive MAC address for a host.
  • If the host is on a different subnet, ARP will actually give you the MAC address for the last router your packet passed through, instead of the MAC address of the host you're scanning.

Put both of these issues 8 together, and that means that one host may 7 have many different MAC addresses (if it 6 has more than one NIC), and one MAC address 5 may represent many different hosts (if traffic 4 passes through a router).

Assuming you know 3 all this and you still need to get the MAC 2 address of a host, the only way to do that 1 in Java is by "going native":

  • Native to the client that runs your program:
    • You could launch an ARP command-line tool and parse its output.
    • You could use some sort of JNI call. I'm not too familiar with JNI, though, so I can't help you with that.
    • Write a separate, small native app that you can access from Java via Telnet or some such protocol, and which will run the ARP command for you.
  • Native to the host that you want to scan:
    • You could use SNMP, as some of the other answers to this thread suggest. I defer to these answers for making that work for you. SNMP is a great protocol, but be aware that SNMP's OIDs can be both platform-dependent and vendor-dependent. OIDs that work for Windows don't always work for Linux and vice versa.
    • If you know that your host runs Windows, you could use WMI. The Win32_NetworkAdapter class holds the information you want, but be aware that this returns all of the hosts NICs, even the ones Windows makes up. Also, it requires administrator credentials to the host you are scanning. Google will tell you how to connect to WMI from Java.
    • If you know your host runs OS X, you might be able to SSH into the machine and parse the output of the system_profile command.
    • For Linux, a tool similar to OS X's system_profile probably exists.
Score: 6

There is a much simpler way:

private static final String ARP_GET_IP_HW = "arp -a";

public String getARPTable(String cmd) throws IOException {
           Scanner s = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
                return s.hasNext() ? s.next() : "";

System.out.println(getARPTable(ARP_GET_IP_HW ));

And you get 5 the eintire ARP Table with IP and HW sorted 4 on each row.

Then you can split the table 3 into separate String rows and use regular 2 expressions on each row to match both HW 1 and IP Adress. And you're done.

Score: 4

The arp cache is provided as standard in 6 the set of SNMP data available. You can 5 use SNMP4J to write a trivial agent to query this 4 data.

e.g. from a command line SNMP toolset

snmpwalk ${hostname}

(that 3 huge period-delimited string is the OID, or 2 identifier, of the ARP cache in SNMP terms. That 1 will work for all SNMP implementations)

Score: 4

ARP is the way to map IP addresses to MAC addresses. That's 10 how the IP stack does it.

I'm not sure there 9 is a portable way to get that info, since 8 it is typically only important for kernel 7 developers and system administrators.

From 6 a lot of web searching, it looks like it 5 is possible to get a router's ARP table 4 using SNMP, but I didn't find a lot of specific 3 info on how to do it. I did find a free 2 Java library for SNMP here though. Some spelunking 1 through there might prove productive.

Score: 4

You can get your own MAC address via:

Enumeration<NetworkInterface> it = NetworkInterface.getNetworkInterfaces();
while ( it.hasMoreElements() ) {
    byte[] macAddress = it.nextElement().getHardwareAddress();

There is definitely 8 no way you can get the MAC address of another 7 host via vanilla java. You'd have to use 6 Process execution or a native library to 5 do it.

If you control the other machines, you 4 can let them query their own MAC and send 3 it back across a TCP/IP channel, but I'm 2 guessing that's not what you want. For more 1 details, see jqno's answer.

Score: 2

This may not be solvable in the context 7 of Java (because it is platform independent), but 6 you should also consider whether or not 5 you can get the MAC addresses via a system 4 service. There are probably situations where 3 you cannot reliably find the MAC address 2 via ARP, it depends on why you would need 1 the MAC address.

Score: 2

As others have said, ARP is the way to go. Following 5 is an implementation of jqnos second suggestion 4 based on this example on GitSpot.

Two libraries are required:

  1. system library for network traffic capture:
  2. the 3 jpcap java library available from the jpcap sourceforge site, which 2 provides a high-level interface to the first 1 library through JNI

    public class GetMACAddress {
     * @param ip address containing an IP
     * @return MAC-Address as formatted String
     * @throws IOException
     * @throws IllegalArgumentException
    public static String getMACAdressByIp(Inet4Address ip) throws IOException, IllegalArgumentException {
        byte[] mac = GetMACAddress.getMACAddressByARP(ip);
        StringBuilder formattedMac = new StringBuilder();
        boolean first = true;
        for (byte b : mac) {
            if (first) {
                first = false;
            } else {
            String hexStr = Integer.toHexString(b & 0xff);
            if (hexStr.length() == 1) {
        return formattedMac.toString();
    private static byte[] getMACAddressByARP(Inet4Address ip) throws IOException, IllegalArgumentException {
        NetworkInterface networkDevice = getNetworkDeviceByTargetIP(ip);
        JpcapCaptor captor = JpcapCaptor.openDevice(networkDevice, 2000, false, 3000);
        captor.setFilter("arp", true);
        JpcapSender sender = captor.getJpcapSenderInstance();
        InetAddress srcip = null;
        for (NetworkInterfaceAddress addr : networkDevice.addresses)
            if (addr.address instanceof Inet4Address) {
                srcip = addr.address;
        byte[] broadcast = new byte[] { (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255 };
        ARPPacket arp = new ARPPacket();
        arp.hardtype = ARPPacket.HARDTYPE_ETHER;
        arp.prototype = ARPPacket.PROTOTYPE_IP;
        arp.operation = ARPPacket.ARP_REQUEST;
        arp.hlen = 6;
        arp.plen = 4;
        arp.sender_hardaddr = networkDevice.mac_address;
        arp.sender_protoaddr = srcip.getAddress();
        arp.target_hardaddr = broadcast;
        arp.target_protoaddr = ip.getAddress();
        EthernetPacket ether = new EthernetPacket();
        ether.frametype = EthernetPacket.ETHERTYPE_ARP;
        ether.src_mac = networkDevice.mac_address;
        ether.dst_mac = broadcast;
        arp.datalink = ether;
        while (true) {
            ARPPacket p = (ARPPacket) captor.getPacket();
            if (p == null) {
                throw new IllegalArgumentException(ip + " is not a local address");
            if (Arrays.equals(p.target_protoaddr, srcip.getAddress())) {
                return p.sender_hardaddr;
    private static NetworkInterface getNetworkDeviceByTargetIP(Inet4Address ip) throws IllegalArgumentException {
        NetworkInterface networkDevice = null;
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        loop: for (NetworkInterface device : devices) {
            for (NetworkInterfaceAddress addr : device.addresses) {
                if (!(addr.address instanceof Inet4Address)) {
                byte[] bip = ip.getAddress();
                byte[] subnet = addr.subnet.getAddress();
                byte[] bif = addr.address.getAddress();
                for (int i = 0; i < 4; i++) {
                    bip[i] = (byte) (bip[i] & subnet[i]);
                    bif[i] = (byte) (bif[i] & subnet[i]);
                if (Arrays.equals(bip, bif)) {
                    networkDevice = device;
                    break loop;
        if (networkDevice == null) {
            throw new IllegalArgumentException(ip + " is not a local address");
        return networkDevice;
Score: 1

Inspired by greenspand answer i came up with this 4 code that will query for the MAC address using IP and 3 CMD command using specified IP.

Note that this 2 code work on Windows and i believe it can work 1 on Linux too with little modifications.

 public static String getARPTable(String ip) throws IOException {
        String systemInput = "";
//to renew the system table before querying 
        Runtime.getRuntime().exec("arp -a");
        Scanner s = new Scanner(Runtime.getRuntime().exec("arp -a " + ip).getInputStream()).useDelimiter("\\A");
        systemInput = s.next();
        String mac = "";
        Pattern pattern = Pattern.compile("\\s{0,}([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})");
        Matcher matcher = pattern.matcher(systemInput);
        if (matcher.find()) {
            mac = mac + matcher.group().replaceAll("\\s", "");
        } else {
            System.out.println("No string found");
        return mac;

    public static void main(String[] args) throws IOException {

        // prints 74-d4-35-76-11-ef

Score: 0

I provided a fully production ready method 2 by using pcap4j+libpcap to detect IPV4 and 1 ipv6 mac address here: https://github.com/gaoxingliang/mac-address-detector-java

More Related questions