With a good understanding of how to view our packets we can now move onto some packet generation. Let’s talk a bit about sniffing first and how existing packets are our best tool for creating new ones.

Sniff() function arguments

We’ve used the sniff() function a couple times already to capture some packets for viewing. I’m going to explain a little bit more about the sniff() function and its arguments. The arguments we will be talking about are:

  • count: Number of packets to capture. 0 means infinity.
  • iface: Sniff for packets only on the provided interface.
  • prn: Function to apply to each packet. If something is returned, it is displayed. For instance you can use prn = lambda x: x.summary().
  • store: Whether to store sniffed packets or discard them. When you only want to monitor your network forever, set store to 0.
  • timeout: Stop sniffing after a given time (default: None).

These should all be self-explanatory except for the filter and prn arguments. The filter argument takes BPF syntax filters, just like Wireshark or tcpdump capture filters. The prn argument is a very cool capability of the sniff() function and you can read more about it here: Scapy and custom actions.

Since we want to generate our first ARP packet we should go ahead and sniff one to see what it takes to recreate one using the .show() and .command() method. Here’s a sniff using the count and filter arguments:

Building a Packet

It looks like ARP packets only have 2 layers plus padding that we have to worry about. We can use the ls() function on the Ether and ARP layers to see what options are available to us:

Let’s create our ARP packet and start assigning some values. We construct a new ARP packet, and use the assignment operator customize specific fields of our packet:

The layers we want are defined with the with the Layer() notation. This will work for any layer in the ls() command output. That’s a lot of options! You can also define the packet from scratch with all the options in one statement by passing in the fields as arguments to the related layer.

Note that the special glue holding these packets together is the / operator. If you happen to forget a layer when you’re first defining the packet, you can add on a layer very easily using the existing packet and the / operator like this:

Sending a packet

Yup, you guessed it, its finally time to send this ARP packet out on the wire! Since ARP is a L2 protocol we’re going to use the sendp() function as the send() function only works with L3 Packets (IP or IPv6 headers):

Screenshot of capture packet in Wireshark

Screenshot of capture packet in Wireshark

What, what! Check that out! Our packet out from the scapy console and in the wire! Pretty cool, right? Well, here’s a fun fact. We don’t need to create and build the packet before sending it, we can define the packet right there in the send() or sendp() function like this:

In fact, we can do some other cool things with these send functions. If we had an array of packets (such as one created with Python loops and some random or incrementing values for IP address/TCP port), the send function would send each packet in that array:

The send commands have some arguments to control the packet sending, here’s the main ones you might consider using:

send(pkts, inter=0, loop=0)
sendp(pkts, inter=0, loop=0)

  • iface: The interface to send the packets out from.
  • inter: Time in seconds to wait between 2 packets.
  • loop: Send the packets endlessly if not 0.
  • pkts: Can be a packet, an implicit packet or a list of them.
Series Navigation<< Scapy p.04 – Looking at PacketsScapy p.06 – Sending and Receiving with Scapy >>

This post was originally published on

This article has 11 comments

  1. Diamond

    Another question that I forgot, is if I set destination IP addresses locally, it give an error like “Mac address to reach destination not found. Using broadcast”

    What should I do?

    Thanks in advance

    1. matw

      I’m not familiar with running python or scapy on Windows, but you can check out instructions for installing and running scapy in Windows here.

      Regarding the broadcast error, check out the explanation here. You might need to use the L2 sendp() function instead of send() and set the src and dest MAC address manually.

      Also, Stack Overflow has an excellent community and several scapy experts with a lot more experience than me. I highly recommend checking this site out, it’s a great resource!

  2. Kashif


    I am trying to send the packets via scapy. It says that the packet is sent but I can’t really capture it via wireshark. I am using windows version of scapy. Can you shed some light on that?

  3. Chris

    Hopefully this will help someone who copies the arppkt example on this page.

    arp doesn’t have an IP layer, therefore it should be defined as:

    arppkt = Ether()/ARP()

Leave a Reply to Kashif Cancel reply

Your email address will not be published. Required fields are marked *