Packet Crafting and Network Exploration with Scapy

According to its main page,

Scapy is a powerful interactive packet manipulation library written in Python. Scapy is able to forge or decode packets of a wide number of protocols, send them on the wire, capture them, match requests and replies, and much more.


Depending on your OS and the installation method you want to use there are several options to install Scapy.

pip install scapy

sudo apt install python3-scapy

git clone

yay -S scapy

sudo scapy

INFO: Can't import PyX. Won't be able to use psdump() or pdfdump().
             apyyyyCY//////////YCa       |
            sY//////YSpcs  scpCY//Pp     | Welcome to Scapy
 ayp ayyyyyyySCP//Pp           syY//C    | Version 2.5.0
 AYAsAYYYYYYYY///Ps              cY//S   |
         pCCCCY//p          cSSps y//Y   |
         SPPPP///a          pP///AC//Y   |
              A//A            cyP////C   | Have fun!
              p///Ac            sC///a   |
              P////YCpc           A//A   | Craft packets before they craft
       scccccp///pSP///p          p//Y   | you.
      sY/////////y  caa           S//P   |                      -- Socrate
       cayCyayP//Ya              pY/Ya   |
        sY/PsY////YCc          aC//Yp 
         sc  sccaCY//PCypaapyCP//YSs  
                                       using IPython 8.20.0

In my case, the first time I ran Scapy I got that INFO message about PyX that disappeared after installing python-pyx.


Scapy can be used either in interactive mode or in python code.

Sending ICMP Ping Request:


Begin emission:
WARNING: Incompatible L3 types detected using <class 'scapy.layers.inet.IP'> instead of <class 'scapy.layers.inet6.IPv46'> !
Finished sending 1 packets.
Received 1 packets, got 1 answers, remaining 0 packets
<IP  version=4 ihl=5 tos=0x0 len=28 id=0 flags= frag=0 ttl=120 proto=icmp chksum=0xfece src= |<ICMP  type=echo-reply code=0 chksum=0xffff id=0x0 seq=0x0 |

Craft and Send Custom TCP Packet:

# Import Scapy
from scapy.all import *

# Craft and send a TCP packet to port 80 on, and capture the response
response = sr1(IP(dst="")/TCP(dport=80), timeout=2)

# Check if a response was received
if response:
    # Display the response details
    print("No response received.")

❯ sudo python

Begin emission:
WARNING: Incompatible L3 types detected using <class 'scapy.layers.inet.IP'> instead of <class 'scapy.layers.inet6.IPv46'> !
Finished sending 1 packets.
Received 1 packets, got 1 answers, remaining 0 packets
###[ IP ]### 
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 44
  id        = 0
  flags     = DF
  frag      = 0
  ttl       = 123
  proto     = tcp
  chksum    = 0x8900
  src       =
  dst       =
  \options   \
###[ TCP ]### 
     sport     = www_http
     dport     = ftp_data
     seq       = 309367137
     ack       = 1
     dataofs   = 6
     reserved  = 0
     flags     = SA
     window    = 65535
     chksum    = 0x7dbf
     urgptr    = 0
     options   = [('MSS', 1289)]

Capture and Display Packets:

pks = sniff(count=5)

<bound method of <Sniffed: TCP:5 UDP:0 ICMP:0 Other:0>>


<bound method of <IP version=4 ihl=5 tos=0x0 len=83 id=60692 flags=DF frag=0 ttl=63 proto=tcp chksum=0x47c7 dst=yyy.yyy.yyy.yyy |<TCP sport=https dport=50686 seq=182204631 ack=2416855860 dataofs=8 reserved=0 flags=PA window=252 chksum=0x941c urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (2129392428, 1421923492))] |<Raw load='\x14\x07\x06\x00\xaa\\xa5\\xdf\\xe0\\x23-Y\\xbc.\x0d\\xc7\\x9e<\\xc2\\xc0\\x8f}\\xd3\\xa0\x0c\\xcbdZ"\x15\\x8b\\xff' |


<bound method of <IP version=4 ihl=5 tos=0x0 len=52 id=53224 flags=DF frag=0 ttl=64 proto=tcp chksum=0x6412 src=yyy.yyy.yyy.yyy |<TCP sport=50686 dport=https seq=2416855860 ack=182204662 dataofs=8 reserved=0 flags=A window=249 chksum=0xd949 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (1421928457, 2129392428))] |


<bound method of <IP version=4 ihl=5 tos=0x0 len=52 id=60693 flags=DF frag=0 ttl=63 proto=tcp chksum=0x47e5 src= dst= |<TCP sport=https dport=50686 seq=182204662 ack=2416855860 dataofs=8 reserved=0 flags=FA window=252 chksum=0xeca9 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (2129392429, 1421923492))] |


<bound method of <IP version=4 ihl=5 tos=0x0 len=52 id=53225 flags=DF frag=0 ttl=64 proto=tcp chksum=0x6411 src= dst= |<TCP sport=50686 dport=https seq=2416855860 ack=182204663 dataofs=8 reserved=0 flags=FA window=249 chksum=0xd946 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (1421928457, 2129392429))] |


<bound method of <IP version=4 ihl=5 tos=0x0 len=52 id=60694 flags=DF frag=0 ttl=63 proto=tcp chksum=0x47e4 src= dst= |<TCP sport=https dport=50686 seq=182204663 ack=2416855861 dataofs=8 reserved=0 flags=A window=252 chksum=0xd926 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (2129392458, 1421928457))] |

And if we ask for another package, it gives an error because we just got 5 packages.


IndexError                                Traceback (most recent call last)
Cell In[19], line 1
----> 1 pks[5].show

File /usr/lib/python3.11/site-packages/scapy/, in _PacketList.__getitem__(self, item)
    173 if isinstance(item, slice):
    174     return self.__class__(self.res.__getitem__(item),
    175                           name="mod %s" % self.listname)
--> 176 return self.res.__getitem__(item)

IndexError: list index out of range