Capturing WiFi Beacon Frames, Probe Requests and Probe Responses in Python with Scapy

WiFi is almost everywhere. Wherever you go there are WiFi packets emitted by smartphones, tablets, computers, access-points, etc. All WiFi packets “flying” around are divided into four main groups (802.11 Frame Types) – management, data, control and extension. In this article we will take care of capturing some interesting subtype packets of management group (Beacon Frames, Probe Requests and Probe Response) using Python with Scapy (see Packet sniffer in Python with Scapy) on Linux (Ubuntu).

Beacon Frames

Becon Frames are transmitted periodically (~100ms) by access-points to announce the presence of a wireless LAN and to synchronise the members (Hi. I’m Mr. AccessPoint. My SSID is XYZ and I’m alive!).

Probe Requests

Devices like for example smartphones are sending a request to nearby wireless access-points to send information about wireless networks that are available for connection (Hello, I’m device. Is any AccessPoint around?).

Probe Response

It is an access-points direct response for a Probe Request and contains an available SSID for connection (Dear device, the content of your kind request is well noted. I’m Mr. AccessPoint and here is my SSID. Feel free to choose me!)

Entering monitor mode

Before we start sniffing a management packets we need to make two configuration steps:

  1. turn off the Network Manager (to stop trying to change settings back to managed mode) and
  2. activate a monitor mode (it will allow to capture all traffic received on a wireless channel).

Note that the name of network interface on your device may differ. If so, change the interface name in the instructions.

sudo service network-manager stop
sudo ifconfig wlo1 down
sudo iwconfig wlo1 mode monitor
sudo ifconfig wlo1 up

You can verify that monitor mode has been set correctly with instruction:

$ iw dev

Interface wlo1
ifindex 3
wdev 0x1
addr 14:15:16:17:18:19
type monitor
channel 1 (2412 MHz), width: 20 MHz (no HT), center1: 2412 MHz
txpower 14.00 dBm

And you can change/flip the channel number after activating monitor mode with that instruction:

sudo iwconfig wlo1 channel 11

Example code of sniffer capturing Beacons and Probe Requests/Responses

#!/usr/bin/env python3

import codecs
from scapy.all import *

def handler(p):
if not (p.haslayer(Dot11ProbeResp) or p.haslayer(Dot11ProbeReq) or p.haslayer(Dot11Beacon)):

rssi = p[RadioTap].dBm_AntSignal
dst_mac = p[Dot11].addr1
src_mac = p[Dot11].addr2
ap_mac = p[Dot11].addr2
info = f"rssi={rssi:2}dBm, dst={dst_mac}, src={src_mac}, ap={ap_mac}"

if p.haslayer(Dot11ProbeResp):
ssid = codecs.decode(p[Dot11Elt].info, 'utf-8')
channel = ord(p[Dot11Elt:3].info)
print(f"[ProbResp] {info}, chan={channel}, ssid=\"{ssid}\"")
elif p.haslayer(Dot11ProbeReq):
print(f"[ProbReq ] {info}")
elif p.haslayer(Dot11Beacon):
stats = p[Dot11Beacon].network_stats()
ssid = str(stats['ssid'])
channel = ord(p[Dot11Elt:3].info)
interval = p[Dot11Beacon].beacon_interval
print(f"[Beacon ] {info}, chan={channel}, interval={interval}, ssid=\"{ssid}\"")

if __name__ == "__main__":
sniff(iface="wlo1", prn=handler, store=0)

Example output result:

Exiting monitor mode

After all we can switch to managed mode and give the control back to Network Manager.

sudo ifconfig wlo1 down
sudo iwconfig wlo1 mode managed
sudo ifconfig wlo1 up
sudo service network-manager start


Leave a Comment