Get MAC Address

I need a cross-platform method for determining the MAC address of a computer at runtime. You can use the "wmi" module for windows, and the only method for Linux that I could find was to run ifconfig and run the regular expression on its output. I do not like to use a package that works only on one OS, and analyzing the output of another program does not look very elegant, not to mention the prone to errors.

Does anyone know a cross platform method (windows and linux) method to get the MAC address? If not, does anyone know of any more elegant methods than the ones I listed above?

+99
python linux windows networking
Oct 01 '08 at 18:51
source share
14 answers

Python 2.5 includes an uuid implementation that (for at least one version) needs a mac address. You can easily import the macro search function into your own code:

from uuid import getnode as get_mac mac = get_mac() 

The return value is the MAC address as an integer of 48 bits.

+143
01 Oct '08 at 19:06
source share

A pure Python solution for this problem under Linux to get the MAC for a specific local interface, originally posted as a comment by vishnubob and improved by Ben Mackey in this activestate recipe

 #!/usr/bin/python import fcntl, socket, struct def getHwAddr(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15])) return ':'.join(['%02x' % ord(char) for char in info[18:24]]) print getHwAddr('eth0') 

This is Python 3 compatible code:

 #!/usr/bin/env python3 # -*- coding: utf-8 -*- import fcntl import socket import struct def getHwAddr(ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15])) return ':'.join('%02x' % b for b in info[18:24]) def main(): print(getHwAddr('enp0s8')) if __name__ == "__main__": main() 
+78
Jan 25 2018-11-11T00:
source share

netifaces is a good module to use to get the mac address (and other addresses). It is cross-platform and makes a little more sense than using a socket or uuid.

 >>> import netifaces >>> netifaces.interfaces() ['lo', 'eth0', 'tun2'] >>> netifaces.ifaddresses('eth0')[netifaces.AF_LINK] [{'addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff'}] 



+29
01 Oct '08 at 18:55
source share

Another thing you should note is that uuid.getnode() can fake a MAC address by returning a random 48-bit number, which might not be what you expect. In addition, there is no explicit indication that the MAC address has been tampered with, but you can find it by calling getnode() twice and seeing if the result changes. If the same value is returned by both calls, you have a MAC address, otherwise you get a fake address.

 >>> print uuid.getnode.__doc__ Get the hardware address as a 48-bit positive integer. The first time this runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with its eighth bit set to 1 as recommended in RFC 4122. 
+21
Oct 02 '08 at 3:49
source share

Sometimes we have several network interfaces.

A simple method for determining the MAC address of a particular interface is

 def getmac(interface): try: mac = open('/sys/class/net/'+interface+'/address').readline() except: mac = "00:00:00:00:00:00" return mac[0:17] 

to call a method just

 myMAC = getmac("wlan0") 
+16
Aug 18 '15 at 19:16
source share

Using my answer from here: https://stackoverflow.com/a/167189/

It would be important to know which iface you need a MAC for, as many may exist (bluetooth, several nics, etc.).

This task is when you know the IP address of the iface, which requires a MAC, using netifaces (available in PyPI):

 import netifaces as nif def mac_for_ip(ip): 'Returns a list of MACs for interfaces that have given IP, returns None if not found' for i in nif.interfaces(): addrs = nif.ifaddresses(i) try: if_mac = addrs[nif.AF_LINK][0]['addr'] if_ip = addrs[nif.AF_INET][0]['addr'] except IndexError, KeyError: #ignore ifaces that dont have MAC or IP if_mac = if_ip = None if if_ip == ip: return if_mac return None 

Testing:

 >>> mac_for_ip('169.254.90.191') '2c:41:38:0a:94:8b' 
+8
Aug 03 '13 at 10:40 on
source share

You can do this with psutil, which is cross-platform:

 import psutil mac_addresses = [] nics = psutil.net_if_addrs() nics.pop('lo') # remove loopback since it doesnt have a real mac address for i in nics: for j in nics[i]: if j.family == 17: # AF_LINK mac_addresses.append(j.address) 
+5
Dec 10 '16 at
source share

Note that you can create your own cross-platform library in python using conditional import. eg.

 import platform if platform.system() == 'Linux': import LinuxMac mac_address = LinuxMac.get_mac_address() elif platform.system() == 'Windows': # etc 

This will allow you to use os.system calls or platform specific libraries.

+3
01 Oct '08 at
source share

The cross-platform getmac package will work for this if you don't mind the dependency. It works with Python 2.7+ and 3.4+. He will try many different methods until he gets the address or returns None.

 from getmac import get_mac_address eth_mac = get_mac_address(interface="eth0") win_mac = get_mac_address(interface="Ethernet 3") ip_mac = get_mac_address(ip="192.168.0.1") ip6_mac = get_mac_address(ip6="::1") host_mac = get_mac_address(hostname="localhost") updated_mac = get_mac_address(ip="10.0.0.1", network_request=True) 

Disclaimer: I am the author of the package.

Update (January 14, 2019): now the package only supports Python 2.7+ and 3.4+. You can still use an older version of the package if you need to work with old Python (2.5, 2.6, 3.2, 3.3).

+1
Aug 02 '18 at 6:28
source share

I don't know about a unified way, but here is something useful:

http://www.codeguru.com/Cpp/IN/network/networkinformation/article.php/c5451

What I would do in this case would be to turn them into a function, and based on the OS, he would execute the correct command, analyze it as necessary, and return only the MAC address formatted as you want. Of course, all this happens, except that you only need to do this once, and it looks cleaner from the main code.

0
01 Oct '08 at 19:02
source share

For Linux, let me introduce a shell script that will show the MAC address and allow it to change (sniffing the MAC).

  ifconfig eth0 | grep HWaddr |cut -dH -f2|cut -d\ -f2 00:26:6c:df:c3:95 

Arguments can be cut by dffer (I'm not an expert):

 ifconfig etho | grep HWaddr eth0 Link encap:Ethernet HWaddr 00:26:6c:df:c3:95 

To change the MAC, we can:

 ifconfig eth0 down ifconfig eth0 hw ether 00:80:48:BA:d1:30 ifconfig eth0 up 

will change the mac address to 00: 80: 48: BA: d1: 30 (temporarily, upon reboot it will be restored to the actual one).

0
Jul 26 '13 at 14:46
source share

On the other hand,

 import uuid mac_id=(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff) 
0
Jan 28 '19 at 10:19
source share

for Linux solution

 INTERFACE_NAME = "eth0" ####################################### def get_mac_id(ifname=INTERFACE_NAME): import commands words = commands.getoutput("ifconfig " + ifname).split() if "HWaddr" in words: return words[ words.index("HWaddr") + 1 ] else: return 'No MAC Address Found!' 

Using:

 print get_mac_id(ifname="eth0") 
-one
Dec 23 '14 at 9:32
source share

For Linux, you can get the MAC address using SIOCGIFHWADDR ioctl.

 struct ifreq ifr; uint8_t macaddr[6]; if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) return -1; strcpy(ifr.ifr_name, "eth0"); if (ioctl(s, SIOCGIFHWADDR, (void *)&ifr) == 0) { if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) { memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6); return 0; ... etc ... 

You noted the question "python". I do not know about the existing Python module to get this information. You can use ctypes to directly call ioctl.

-8
01 Oct '08 at 19:12
source share



All Articles