MAC Addresses Explained: What They Are, How They Work, and Why Developers Should Care
Source: Dev.to
What is a MAC address?
Every network interface on every device in the world has a MAC address. Your laptop, phone, smart fridge, printer — they all have at least one.
MAC stands for Media Access Control. It is a unique identifier assigned to a network interface controller (NIC) — the hardware that connects your device to a network.
A MAC address looks like this:
00:1A:2B:3C:4D:5E
It is 48 bits (6 bytes) long, usually written as six pairs of hexadecimal digits separated by colons or hyphens.
Structure of a MAC address
| Part | Size | Example |
|---|---|---|
| OUI (Organizationally Unique Identifier) | 3 bytes | 00:1A:2B |
| NIC‑specific | 3 bytes | 3C:4D:5E |
- The first three bytes identify the manufacturer. The IEEE assigns OUI blocks to companies.
- The last three bytes are assigned by the manufacturer to uniquely identify each device. With 24 bits, each OUI block supports ~16.7 million unique devices.
OUI examples
| OUI | Manufacturer |
|---|---|
00:00:0C | Cisco |
00:1A:11 | |
3C:22:FB | Apple |
DC:A6:32 | Raspberry Pi |
00:50:56 | VMware |
Important flags in the first byte
| Bit | Meaning |
|---|---|
| 0 (LSB) | 0 = Unicast, 1 = Multicast |
| 1 | 0 = Globally unique, 1 = Locally administered |
Examples
00:1A:2B:…→ Bit 0 = 0, Bit 1 = 0 → Unicast, globally unique (normal)01:00:5E:…→ Bit 0 = 1 → Multicast address02:42:AC:…→ Bit 1 = 1 → Locally administered (Docker uses these)
Docker and locally administered MACs
Docker assigns locally administered MAC addresses to containers:
docker inspect -f '{{.NetworkSettings.MacAddress}}' my-container
# Output: 02:42:ac:11:00:02
The 02 prefix indicates the locally‑administered flag is set.
Virtualization platforms
| Platform | OUI used |
|---|---|
| VMware | 00:50:56 |
| VirtualBox | 08:00:27 |
These platforms generate MAC addresses for virtual NICs using their assigned OUIs.
Common uses on local networks
# List devices on your network
arp -a
# Or use nmap
nmap -sn 192.168.1.0/24
Wake‑on‑LAN (WoL)
WoL uses MAC addresses to wake sleeping devices by sending a “magic packet” that repeats the target’s MAC address 16 times:
import socket
def wake_on_lan(mac):
mac_bytes = bytes.fromhex(mac.replace(':', ''))
magic = b'\xff' * 6 + mac_bytes * 16
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
sock.sendto(magic, ('255.255.255.255', 9))
wake_on_lan('00:1A:2B:3C:4D:5E')
MAC vs. IP address
| Property | MAC Address | IP Address |
|---|---|---|
| Layer | Data Link (Layer 2) | Network (Layer 3) |
| Scope | Local network only | Global (routable) |
| Assignment | Hardware/manufacturer | DHCP / manual |
| Format | 48‑bit hex | 32‑bit (IPv4) or 128‑bit (IPv6) |
| Changes? | Usually permanent* (can be randomized) | Can change per network |
| Example | 00:1A:2B:3C:4D:5E | 192.168.1.100 |
*Modern devices often randomize MAC addresses for privacy (see below).
MAC randomization
Starting around 2014, mobile operating systems began randomizing MAC addresses for Wi‑Fi scanning to prevent tracking:
| OS / Version | Default behavior |
|---|---|
| iOS 14+ | Random MAC per network |
| Android 10+ | Random MAC per network |
| Windows 10/11 | Optional random hardware addresses |
| macOS Sequoia+ | Random Wi‑Fi addresses |
This broke many assumptions in networking—captive portals, device tracking, DHCP reservations, and parental controls all relied on stable MAC addresses.
Viewing MAC addresses on different OSes
# macOS
ifconfig en0 | grep ether
# Linux
ip link show
# or
cat /sys/class/net/eth0/address
# Windows (Command Prompt)
ipconfig /all
# or
getmac
Formatting variations
| Format | Example | Used By |
|---|---|---|
| Colon‑separated | 00:1A:2B:3C:4D:5E | Linux, macOS |
| Hyphen‑separated | 00-1A-2B-3C-4D-5E | Windows |
| Dot‑separated | 001A.2B3C.4D5E | Cisco |
| No separator | 001A2B3C4D5E | Some APIs |
All represent the same address—just formatted differently.
MAC addresses and IPv6 (EUI‑64)
IPv6 can derive interface identifiers from MAC addresses using the EUI‑64 format:
- Insert
FF:FEin the middle
00:1A:2B:3C:4D:5E→00:1A:2B:FF:FE:3C:4D:5E - Flip the 7th bit (the “U/L” bit)
00:1A:2B:FF:FE:3C:4D:5E→02:1A:2B:FF:FE:3C:4D:5E
Resulting IPv6 link‑local address:
fe80::21a:2bff:fe3c:4d5e
MAC randomization therefore also impacts IPv6 privacy.
Generating valid MAC addresses for testing
If you need realistic MAC addresses for development or documentation, randommac.com generates them instantly with proper structure—valid OUI prefixes, correct flag bits, and multiple output formats. No signup required; works directly in the browser.
Conclusion
MAC addresses are a networking fundamental that most developers interact with more often than they realize. Docker containers, virtual machines, IoT devices, and network debugging all rely on them. Understanding the structure, flags, and vendor prefixes helps you troubleshoot faster and build better network‑aware applications.
What’s your most interesting MAC‑address debugging story? Share it in the comments!