Build a Network Sniffer in Python Using Scapy


Introduction
Monitoring network traffic is a powerful technique used in cybersecurity, troubleshooting, and system analysis. A network sniffer captures packets in real-time to inspect the data being transmitted on a network.
In this article, we’ll use Scapy, a popular Python-based packet manipulation tool, to build a simple network sniffer. You'll learn how to capture and display key information such as IP addresses, protocols, ports, and packet summaries.
Legal Disclaimer
Before we dive in:
Do not sniff traffic on networks you do not own or have explicit permission to monitor. Unauthorized packet sniffing can violate privacy laws and is illegal in many jurisdictions. Use this tool responsibly and only in test environments or on networks you are authorized to inspect.
What is Scapy?
Scapy is a powerful Python library for:
Capturing packets
Crafting and sending packets
Performing network scans
Analyzing protocols
Unlike raw socket programming, Scapy simplifies working with low-level network packets.
Step-by-Step Sniffer Implementation
Let’s walk through building the sniffer.
Step 1: Install Scapy
Run this in your terminal or command prompt:
pip install scapy
Depending on your OS, you may need administrator/root privileges to sniff packets.
Step 2: Import Required Modules
from scapy.all import sniff, IP, TCP, UDP, ICMP
We import:
sniff
: for capturing packetsIP
,TCP
,UDP
,ICMP
: protocol-specific layers we’ll inspect
Step 3: Define the Packet Handler Function
def process_packet(packet):
if IP in packet:
ip_layer = packet[IP]
src = ip_layer.src
dst = ip_layer.dst
proto = ip_layer.proto
print(f"[IP] {src} → {dst} | Protocol: {proto}")
if TCP in packet:
tcp = packet[TCP]
print(f" └── [TCP] Port: {tcp.sport} → {tcp.dport}")
elif UDP in packet:
udp = packet[UDP]
print(f" └── [UDP] Port: {udp.sport} → {udp.dport}")
elif ICMP in packet:
print(f" └── [ICMP] Type: {packet[ICMP].type}")
Here’s what’s happening:
If the packet has an IP layer, we extract source/destination IPs and protocol.
If TCP, UDP, or ICMP is present, we extract port numbers or type info.
Step 4: Start Sniffing Packets
def start_sniffing(interface=None, packet_count=0):
print(f"\n[+] Starting packet sniffing on interface: {interface or 'default'}...\n")
sniff(iface=interface, prn=process_packet, count=packet_count, store=False)
iface
: You can pass an interface like"eth0"
or"Wi-Fi"
(optional).prn
: Specifies the function to process each packet.count
: 0 means sniff indefinitely.store=False
: Avoids storing packets in memory (efficient for long runs).
Step 5: Main Function with User Input
if __name__ == "__main__":
print("Python Network Sniffer (Scapy)")
iface = input("Enter interface name (leave blank for default): ").strip()
count_input = input("How many packets to capture? (0 for infinite): ").strip()
try:
count = int(count_input) if count_input else 0
except ValueError:
count = 0
start_sniffing(interface=iface if iface else None, packet_count=count)
This allows the user to:
Specify a network interface.
Choose how many packets to sniff.
Full Script
from scapy.all import sniff, IP, TCP, UDP, ICMP
def process_packet(packet):
if IP in packet:
ip_layer = packet[IP]
src = ip_layer.src
dst = ip_layer.dst
proto = ip_layer.proto
print(f"[IP] {src} → {dst} | Protocol: {proto}")
if TCP in packet:
tcp = packet[TCP]
print(f" └── [TCP] Port: {tcp.sport} → {tcp.dport}")
elif UDP in packet:
udp = packet[UDP]
print(f" └── [UDP] Port: {udp.sport} → {udp.dport}")
elif ICMP in packet:
print(f" └── [ICMP] Type: {packet[ICMP].type}")
def start_sniffing(interface=None, packet_count=0):
print(f"\n[+] Starting packet sniffing on interface: {interface or 'default'}...\n")
sniff(iface=interface, prn=process_packet, count=packet_count, store=False)
if __name__ == "__main__":
print("Python Network Sniffer (Scapy)")
iface = input("Enter interface name (leave blank for default): ").strip()
count_input = input("How many packets to capture? (0 for infinite): ").strip()
try:
count = int(count_input) if count_input else 0
except ValueError:
count = 0
start_sniffing(interface=iface if iface else None, packet_count=count)
Conclusion
You now have a functional, flexible Python-based network sniffer that displays live packet data including IPs, protocols, and ports. This is a solid starting point for learning about network traffic and building more advanced tools like:
Packet loggers
Protocol analyzers
Intrusion detection prototypes
Subscribe to my newsletter
Read articles from Michelle Mukai directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
