Google is committed to advancing racial equity for Black communities. See how.

Packet Sniffing with Pyspinel

The Pyspinel sniffer tool connects to a Thread NCP or RCP device and converts it into a promiscuous packet sniffer, generating a pcap (packet capture) stream to be saved or piped directly into Wireshark.

Wireshark is an open-source tool that can decode network protocols in the Thread stack, such as IEEE 802.15.4, 6LoWPAN, IPv6, MLE (Mesh Link Establishment), UDP, and CoAP.

This guide covers how to configure Wireshark and run Pyspinel to sniff packets from a Thread network.

To use the Wireshark extcap plugin for packet sniffing, see Packet Sniffing using extcap.



  • A host machine to serve as an NCP and to run Pyspinel and Wireshark:
    • macOS — 64 bit OS X 10.6 or later
    • Ubuntu
  • 1 OpenThread device flashed with an ot-ncp-ftd or ot-rcp build.



Set up the sniffer environment

Clone and install Pyspinel and dependencies:

  1. Install dependencies:
    sudo apt install python3-pip
    pip3 install --user pyserial ipaddress
  2. Clone the Pyspinel repository:
    git clone
  3. Install Pyspinel:
    cd pyspinel
    python3 install

Alternatively, set up the environment by installing the pyspinel package. Note that this package uses the Pyspinel v1.0.0a3 release and not the latest Pyspinel main.

pip3 install --user pyspinel

Install Wireshark


Open a terminal and run the following commands to download and install Wireshark:

sudo add-apt-repository ppa:wireshark-dev/stable
sudo apt-get update
sudo apt-get install wireshark

We recommend running Wireshark as a non-root user. To do so, reconfigure the package:

sudo dpkg-reconfigure wireshark-common

When you get the dialog asking "Should non-superusers be able to capture packets?", select Yes, then add the wireshark user and update file permissions:

sudo adduser $USER wireshark
sudo chmod +x /usr/bin/dumpcap


Download and install Wireshark for macOS.

Build the sniffer

Build and flash an NCP device to serve as the sniffer, using the ot-rcp binary output.

Nordic nRF52840

To set up the Nordic nRF52840 example for use as a sniffer:

  1. Clone openthread/ot-nrf528xx and set up the build environment:
    git clone --recursive
  2. Set baud rate as 460800. Find the line #define UART_BAUDRATE NRF_UARTE_BAUDRATE_115200 in src/nrf52840/transport-config.h, and replace it with #define UART_BAUDRATE NRF_UARTE_BAUDRATE_460800.
  3. Build the binary:
    ./script/build nrf52840 UART_trans
  4. Convert the ot-rcp binary output to hex:
    arm-none-eabi-objcopy -O ihex build/bin/ot-rcp ot-rcp.hex
  5. Flash the ot-rcp.hex file to the nRF52840 board as detailed in Flash the nRF52840.
  6. Disable Mass Storage Device (MSD) on the nRF52840 to avoid issues with data corruption or drops when using the debug port:
    expect <<EOF
    spawn JLinkExe
    expect "J-Link>"
    send "msddisable\n"
    expect "Probe configured successfully."
    spawn JLinkExe
    SEGGER J-Link Commander V6.42b (Compiled Feb  5 2019 17:35:31)
    DLL version V6.42b, compiled Feb  5 2019 17:35:20
    Connecting to J-Link via USB...O.K.
    Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Jan  7 2019 14:07:15
    Hardware version: V1.00
    S/N: 683411111
    Type "connect" to establish a target connection, '?' for help
    Probe configured successfully.

Thread network properties

Before continuing, get the following properties for the Thread network you wish to sniff. You'll need them for Wireshark configuration and running the Pyspinel sniffer.

Mesh Local Prefix

To get the Mesh Local Prefix from a device in the target Thread network:

  1. Using the OpenThread CLI:
    dataset active
    Mesh Local Prefix: fd33:3333:3344:0/64
  2. Using wpanctl with an NCP:
    wpanctl getprop IPv6:MeshLocalPrefix
    IPv6:MeshLocalPrefix = "fd33:3333:3344:0::/64"
  3. Using the OTBR Web GUI, select Status. The Mesh Local Prefix is listed as IPv6:MeshLocalPrefix similar to wpanctl.


To get the Channel from a device in the target Thread network:

  1. Using the OpenThread CLI:
  2. Using wpanctl with an NCP:
    wpanctl getprop NCP:Channel
    NCP:Channel = 15
  3. Using the OTBR Web GUI, select Status. The Channel is listed as NCP:Channel similar to wpanctl.

Network Key

The Thread Network Key is used by Wireshark to decrypt packets after capture. To get the Network Key from a device in the target Thread network:

  1. Using the OpenThread CLI:
  2. Using wpanctl with an NCP:
    wpanctl getprop Network:Key
    Network:Key = [33334444333344443333444433334444]

The Thread Network Key is not available in the OTBR Web GUI.

Wireshark configuration - Protocols

Wireshark must be configured to properly show Thread packets.

Select Preferences... in Wireshark and expand the Protocols section.


Select 6LoWPAN from the list of protocols and verify or change the following settings:

  1. Uncheck Derive ID according to RFC 4944.
  2. Update Context 0 with the Mesh Local Prefix for the target Thread network.
OT Sniffer Wireshark 6LoWPAN

Wireshark uses context configurations to parse the compressed IPv6 address and display the IPv6 source and destination addresses correctly.

To show the addresses for other on-mesh prefixes configured on the gateway, update other Context IDs with those prefixes.

To get the Context ID for a specific on-mesh prefix, view the Thread Network Data TLV in any MLE Data response message. For example:

Context 1: fd00:7d03:7d03:7d03::/64


Select CoAP from the list of protocols and set CoAP UDP Port to 61631. This ensures TMF messages (like address solicit) are displayed.

IEEE 802.15.4

Select IEEE 802.15.4 from the list of protocols and verify or change the following settings:

  1. Set 802.15.4 Ethertype (in hex) to "0x809a".
  2. Set the Security Suite to "AES-128 Encryption, 32-bit Integrity Protection".
  3. Click the Edit... button next to Decryption Keys, which is where you add the Thread network Master Key for packet decryption.
    1. Click + to add a Decryption key.
    2. Enter the Thread network Master Key into the Decryption key column.
    3. Enter "1" as the Decryption key index.
    4. Select Thread hash from the Key hash column listbox.
    5. OT Sniffer Wireshark IEEE 802.15.4
    6. Click OK to save the decryption key.


Select Thread from the list of protocols and verify or change the following settings:

  1. Enter "00000000" for the Thread sequence counter.
  2. Uncheck Use PAN ID as first two octets of master key.
  3. Check Automatically acquire Thread sequence counter.

Click the OK button to save any protocol changes.

Some Thread traffic might be analyzed as the ZigBee protocol. To correctly display these two protocols, edit the enabled protocols in Wireshark:

  1. In Wireshark, go to Analyze > Enabled Protocols.
  2. Uncheck the following protocols:
    1. LwMesh
    2. ZigBee
    3. ZigBee Green Power

Wireshark configuration - RSSI

To display RSSI in Wireshark:

  1. Go to Preferences > Protocols > IEEE 802.15.4.
  2. Set the FCS Format:
    • If IEEE 802.15.4 TAP disabled: TI CC24xx metadata.
    • If IEEE 802.15.4 TAP enabled: ITU-T CRC-16. See the --tap flag for more information.
  3. Click OK to save and return to the Preferences menu.
  4. From Preferences, select Appearance > Columns.
  5. Add a new entry:
    • Title: RSSI
    • Type: Custom
    • Fields: wpan.rssi
OT Sniffer Wireshark RSSI

Sniffer options

-u or --uart
Default value
None - must be provided if you are using a device with a serial connection and not a socket connection.
The -u or --uart flag followed by a device path such as /dev/ttyUSB0.
-c or --channel
Default value
The -c or --channel flag followed by the channel configured on your Thread Network, upon which to sniff packets.
Default value
This flag overrides the default behavior.
The --no-reset flag is needed if your NCP device is connected to the host with the native USB connection.
Default value
This flag overrides the default behavior.
The --crc flag is needed for platforms such as TI and Nordic Semiconductor Thread boards. The flag recalculates the CRC to avoid a ‘Bad FCS' (frame check sequence) warning in Wireshark.
-b or --baudrate
Default value
The -b or --baudrate flag is used to override the default baud rate. Set this value to the same baud rate used with your NCP build (we recommend 460800).
Default value
This flag overrides the default behavior.
The --rssi flag is used to ensure the RSSI is included in the pcap output. You must use this flag if the TI CC24xx FCS format option is enabled in Wireshark.
Default value
This flag overrides the default behavior.
The --tap flag specifies DLT_IEEE802_15_4_TAP(283) for the frame format, with a pseudo-header containing TLVs with metadata (such as FCS, RSSI, LQI, Channel). If not specified, DLT_IEEE802_15_4_WITHFCS(195) would be used by default with the additional RSSI and LQI following the PHY frame directly, as in TI CC24xx FCS format. You must use this flag if the ITU-T CRC-16 option is enabled in Wireshark. If that option is not enabled in Wireshark, do not use this flag.

Run the sniffer

Make sure to use the specific device path for your NCP and the channel for the Thread network you are attempting to sniff.

If following this guide, the nRF52840 DK should be attached the host machine by the debug port, as described in Flash the nRF52840. To run the Pyspinel sniffer, use the -b flag to specify the baud rate (if it was changed from the default) and omit the --no-reset flag.

For example, to sniff on Channel 15 using a device mounted at /dev/ttyACM0 with RSSI included in the Wireshark output:

cd <path-to-pyspinel>
python -c 15 -u /dev/ttyACM0 --crc --rssi -b 460800 | wireshark -k -i -

You should now be able to see the packets and related protocols for this configuration in Wireshark:

Wireshark Capture

See the Spinel sniffer reference for more information on running the Pyspinel sniffer.

Native USB connection

Using the nRF52840 DK USB port requires the OpenThread ot-rcp binary to be built with USB_trans:

./script/build nrf52840 USB_trans

Flash the nRF52840 DK, connect it to the host machine by the USB port, then use the --no-reset flag but omit the -b flag when running the sniffer:

python -c 15 -u /dev/ttyACM0 --crc --no-reset --rssi | wireshark -k -i -


For more information on how to use Pyspinel and Wireshark, see the following: