Build a Network Sniffer in Python Using Scapy

Michelle MukaiMichelle Mukai
3 min read

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.

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 packets

  • IP, 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

0
Subscribe to my newsletter

Read articles from Michelle Mukai directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Michelle Mukai
Michelle Mukai