Getting MAC Address

173,488

Solution 1

Python 2.5 includes an uuid implementation which (in at least one version) needs the mac address. You can import the mac finding function into your own code easily:

from uuid import getnode as get_mac
mac = get_mac()

The return value is the mac address as 48 bit integer.

Solution 2

The 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 on 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 the 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()

Solution 3

netifaces is a good module to use for getting the mac address (and other addresses). It's crossplatform and makes a bit more sense than using 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'}]

Solution 4

Sometimes we have more than one net interface.

A simple method to find out the mac address of a specific 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 the method is simple

myMAC = getmac("wlan0")

Solution 5

One other thing that you should note is that uuid.getnode() can fake the MAC addr by returning a random 48-bit number which may not be what you are expecting. Also, there's no explicit indication that the MAC address has been faked, but you could detect it by calling getnode() twice and seeing if the result varies. If the same value is returned by both calls, you have the MAC address, otherwise you are getting a faked 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.
Share:
173,488
Anna
Author by

Anna

Updated on July 30, 2022

Comments

  • Anna
    Anna almost 2 years

    I need a cross platform method of determining the MAC address of a computer at run time. For windows the 'wmi' module can be used and the only method under Linux I could find was to run ifconfig and run a regex across its output. I don't like using a package that only works on one OS, and parsing the output of another program doesn't seem very elegant not to mention error prone.

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

  • sath garcia
    sath garcia over 15 years
    I just tried this on a Windows box and it works great... except that the laptop I tried it on has 2 NICs (one wireless) and there's no way to determine which MAC it returned. Just a word of warning if you want to use this code.
  • Martin Beckett
    Martin Beckett over 15 years
    Thats a feature of the windows device enumerator, whatever method you use to get the address - you have to be carefull if using it as a unique ID.
  • Aatch
    Aatch almost 13 years
    -1 He wants a python solution, so you go and give him the same regurgitated C solution plastered throughout the web.
  • Aatch
    Aatch almost 13 years
    Used it personally, requires a specific install/compile on each system but works well.
  • Frédéric Grosshans
    Frédéric Grosshans almost 12 years
    Not that the value of the 8th is 1 precisely because it cannot be used by a network card. Just checking this bit is enough to detect whether the address is faked or not.
  • Frédéric Grosshans
    Frédéric Grosshans almost 12 years
    The check is just done with: if (mac >> 40)%2 : raise OSError, "The system does not seem to have a valid MAC"
  • deinonychusaur
    deinonychusaur over 11 years
    Just a warning: If you look at the getnode documentation it says that it will return a random long if it fails to detect the mac: "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." So check that eighth bit!
  • screenshot345
    screenshot345 about 10 years
    hex(mac) to get the familiar hex format of the mac
  • tomlogic
    tomlogic over 9 years
    Or ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2)) for an uppercase MAC with each byte separated by a colon.
  • nu everest
    nu everest over 9 years
    getnode() returns something different every time I restart my windows 7 laptop.
  • chris
    chris almost 9 years
    @deinonychusaur I have a valid mac address where the least significant bit of the first octect is 1. So it seems this is not enough to verify the return value. However, mhawke provides a solution in his answer below that might work.
  • pQuestions123
    pQuestions123 about 8 years
    Does this have to do anything with the question?
  • Bryce Guinta
    Bryce Guinta over 7 years
    Or ':'.join((itertools.starmap(operator.add, zip(*([iter("%012X" % mac)] * 2))))), an alternative way of doing it @tomlogic
  • Richard Aplin
    Richard Aplin over 7 years
    that bit me in the ass - on an embedded system it returned random value if ethernet jack not connected, however reading /sys/class/net/eth0/address (or parsing output of ifconfig) works either connected or not
  • RandomInsano
    RandomInsano over 6 years
    Not super useful for OS X or Windows. :|
  • svenyonson
    svenyonson about 6 years
    @tomlogic - that works excellent!! Very cryptic, but nice one liner that does just what I needed. ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))
  • MikeT
    MikeT over 5 years
    Perfect for Pis!
  • Stefano
    Stefano over 5 years
    that's not really an answer - just a comment
  • Donn Lee
    Donn Lee over 4 years
    import socket then [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET] results in ['ab:cd:ef:01:02:03']
  • Napolean
    Napolean over 2 years
    Standard output for above variables: None None None None 00:00:00:00:00:00 None
  • Ghost of Goes
    Ghost of Goes over 2 years
    Those are just examples of usage. You need to replace the arguments with the values applicable to your system, which is very likely why you're getting null results. For example, "eth0" is not applicable to a Windows system, and "Ethernet 3" isn't applicable to a Linux system, but both are included above as examples so you know how to use the library on both platforms. Note: "localhost" will always return "00:00:00:00:00:00".
  • Sean McCarthy
    Sean McCarthy about 2 years
    Beautiful, works like a charm!
  • Pedro A. Aranda
    Pedro A. Aranda about 2 years
    return mac.strip() may be easier to get rid of the newline ;-)