Wireshark is known as an Ethernet protocol analyzer. But it can also capture Modbus RTU traffic over RS-485 serial links — using a free extension called WiresharkSerialAdapter.
This is not a built-in feature. Wireshark does not natively capture from COM ports. You need a USB-to-RS-485 adapter connected to the bus as a passive listener, plus the WiresharkSerialAdapter extension and a DLT configuration that tells Wireshark to decode the incoming serial bytes as Modbus RTU frames.
Once configured, Wireshark decodes every Modbus RTU frame — slave address, function code, register addresses, data values, and CRC-16 — exactly like it does for Modbus TCP. The same modbus.* display filters work on RTU frames.
This guide walks through the full setup: hardware connection, extension installation, COM port configuration, DLT mapping, display filters, and how to troubleshoot Modbus RTU problems using the captured data.
In This Guide
1. What You Need
| Item | Purpose |
|---|---|
| Wireshark (latest version) | Protocol analyzer |
| WiresharkSerialAdapter extension | Enables serial COM port capture in Wireshark |
| USB-to-RS-485 adapter | Connects your computer to the RS-485 bus |
| RS-485 wiring to the existing bus | Passive listen-only connection |
The USB-to-RS-485 adapter must be connected as a passive listener — wired in parallel on the A/B lines of the existing Modbus RTU bus. It does not transmit. It only receives.
2. How Modbus RTU Appears in Wireshark
Once configured, Wireshark shows Modbus RTU frames with two protocol layers:
| Layer | What It Shows |
|---|---|
| Modbus RTU (mbrtu) | Unit ID (slave address), CRC-16, CRC status |
| Modbus (modbus) | Function code, register addresses, data values, exception codes |
The Info column shows:
Query: Unit: 1, Func: 3: Read Holding Registers
Response: Unit: 1, Func: 3: Read Holding Registers
Query: Unit: 2, Func: 6: Write Single Register
Response: Unit: 2, Func: 6: Write Single Register
This is almost identical to Modbus TCP, except there is no MBAP header. Instead, you see the Unit ID and CRC-16 from the RTU frame.
3. Hardware Setup: Connecting to the RS-485 Bus
Wiring
Connect the USB-to-RS-485 adapter in parallel to the existing Modbus RTU bus:
- A (Data+) on the adapter → A (Data+) on the bus
- B (Data-) on the adapter → B (Data-) on the bus
- GND on the adapter → GND on the bus (recommended)
The adapter is a passive listener. It does not transmit, so it will not interfere with existing communication.
Important
- The adapter must use the same baud rate, parity, and stop bits as the existing Modbus RTU devices.
- If the adapter is at the end of the bus, it may need a 120Ω termination resistor. If it is tapped in the middle of the bus, no termination is needed.
- Note which COM port Windows assigns to the adapter (check Device Manager → Ports).
4. Installing the WiresharkSerialAdapter Extension
Wireshark does not capture from serial ports by default. The WiresharkSerialAdapter extension adds this capability.
Step 1. Download
Go to: github.com/jzhvymetal/WiresharkSerialAdapter
Navigate to the latest version folder (e.g., VSCODE_v6) and download WiresharkSerialAdapter.exe.
Step 2. Install
Copy WiresharkSerialAdapter.exe to the following folder:
C:\Program Files\Wireshark\extcap\wireshark
If the wireshark subfolder inside extcap does not exist, create it.
Step 3. Verify
Restart Wireshark. On the start screen, you should see a new capture interface:
Serial Port Adapter (WireSharkSerialAdapter.exe)
If it does not appear, check that the file is in the correct folder and that Wireshark has been restarted.
5. Configuring the COM Port in Wireshark
Click the settings icon next to “Serial Port Adapter (WireSharkSerialAdapter.exe)” on the Wireshark start screen.
Configure the following settings to match your Modbus RTU network:
| Setting | Value | Notes |
|---|---|---|
| Port | COM7 (example) | The COM port assigned to your USB-to-RS-485 adapter |
| Baud Rate | 9600, 19200, 38400, etc. | Must match the Modbus RTU bus baud rate |
| Byte Size | 8 | Standard for Modbus RTU |
| Parity | EVEN, ODD, or NONE | Must match the bus configuration |
| Stop Bits | 1 or 2 | Must match the bus configuration |
| Interframe Timing Detection | Event | Recommended setting |
| Interframe Timebase | Multiplier: 1X Modbus Character | Based on the Modbus RTU 3.5-character silence specification |
| Interframe Multiplier | 3.0 | 3.0× character time = standard Modbus RTU interframe gap |
| Interframe Delay (µs) | 0.0 | Leave at 0 unless you have specific timing issues |
| Interframe Correction | Modbus CRC | Uses CRC validation to correct frame boundaries |
| Wireshark DLT | 147: User DLT | This maps to User 0 in the DLT_User protocol settings |
Click Save.
⚠️ Critical: If the baud rate, parity, or stop bits do not match the bus, Wireshark will capture garbage data or no data at all.
6. Configuring DLT 147 for the mbrtu Dissector
The WiresharkSerialAdapter sends raw serial bytes to Wireshark using DLT 147 (User 0). You must tell Wireshark to decode these bytes as Modbus RTU frames.
Step 1. Open Preferences
Go to Edit → Preferences → Protocols → DLT_USER
Step 2. Edit the Encapsulations Table
Click Edit next to “Encapsulations Table.” Click the + button to add a new entry.
Step 3. Configure the Entry
| Field | Value |
|---|---|
| DLT | User 0 (DLT=147) |
| Payload dissector | mbrtu |
| Header size | 0 |
| Header dissector | (empty) |
| Trailer size | 0 |
| Trailer dissector | (empty) |
Step 4. Apply
Click OK to close the DLT table, then OK again to close Preferences.
Now Wireshark knows that any data arriving on DLT 147 should be decoded using the mbrtu (Modbus RTU) dissector.
7. Starting a Capture
- On the Wireshark start screen, double-click Serial Port Adapter (WireSharkSerialAdapter.exe)
- Wireshark starts capturing from the COM port
- If the Modbus RTU bus is active, you should see frames appearing immediately
- The Protocol column shows Modbus RTU
- The Info column shows the function code and register information
- Stop the capture by clicking the red Stop button
- Save the capture: File → Save As → choose a filename with
.pcapngextension
8. Display Filters for Modbus RTU
The mbrtu dissector has its own filters for the RTU-specific fields. The standard modbus.* filters work for function codes, register addresses, and data values.
All filters verified against the official Wireshark Modbus RTU Display Filter Reference and Modbus Display Filter Reference.
Modbus RTU Filters (mbrtu)
| Filter | What It Shows |
|---|---|
mbrtu | All Modbus RTU frames |
mbrtu.unit_id | Unit ID (slave address) field |
mbrtu.unit_id == 1 | Only traffic to/from slave address 1 |
mbrtu.unit_id == 2 | Only traffic to/from slave address 2 |
mbrtu.crc16 | CRC-16 value |
mbrtu.crc16.status | CRC-16 check status |
mbrtu.crc16.incorrect | Frames with incorrect CRC |
Modbus Application Layer Filters (same as Modbus TCP)
| Filter | What It Shows |
|---|---|
modbus.func_code == 3 | Read Holding Registers (FC 03) |
modbus.func_code == 4 | Read Input Registers (FC 04) |
modbus.func_code == 6 | Write Single Register (FC 06) |
modbus.func_code == 16 | Write Multiple Registers (FC 16) |
modbus.func_code >= 128 | All exception responses |
modbus.exception_code | Exception code value |
modbus.exception_code == 2 | Illegal Data Address exceptions |
modbus.reference_num | Register address |
modbus.reference_num == 100 | Requests targeting register 100 |
modbus.data | Response data bytes |
Combination Examples
All traffic to slave 1 with exception responses:
mbrtu.unit_id == 1 && modbus.func_code >= 128
Only FC 03 requests to slave 5:
mbrtu.unit_id == 5 && modbus.func_code == 3
Frames with CRC errors:
mbrtu.crc16.incorrect
9. How to Read a Decoded Modbus RTU Frame
Click on a Modbus RTU frame. The packet detail pane shows two sections:
Modbus RTU Section
Modbus RTU
Unit ID: 1
CRC-16: 0xB5C4
[CRC-16 Status: Good]
Modbus Section (same as TCP)
For a Read Holding Registers request:
Modbus
.000 0011 = Function Code: Read Holding Registers (3)
Reference Number: 100
Word Count: 6
For the response:
Modbus
.000 0011 = Function Code: Read Holding Registers (3)
[Request Frame: 43]
[Time from request: 0.248228000 seconds]
Byte Count: 12
Register 105 (UINT16): 6867
Register 106 (UINT16): 0
Register 107 (UINT16): 3
Register 108 (UINT16): 0
Register 109 (UINT16): 89
Register 110 (UINT16): 3400
Wireshark automatically links the request and response frames. Click [Request Frame: 43] to jump to the matching request.
10. Filtering by Slave Address (Unit ID)
On a busy Modbus RTU bus with many slaves, isolating traffic for one device is essential.
Filter: mbrtu.unit_id == 2
This shows only frames addressed to or from slave 2. You can then save the filtered view to a separate file: File → Export Specified Packets → Displayed to create a smaller capture file for analysis or sharing.
11. Diagnosing No Response from a Slave
Filter: mbrtu.unit_id == <slave address>
| What You See | Cause | Fix |
|---|---|---|
| Query frames but no Response frames | Slave is not responding | Check slave power, wiring, and address configuration |
| No frames at all for this address | Master is not polling this slave | Check master configuration |
| Query sent to wrong address | Master is configured with wrong slave address | Verify the address in the master/SCADA configuration |
| Response from a different slave address | Slave address conflict — two devices with the same address | Assign unique addresses to all devices on the bus |
12. Diagnosing CRC Errors
Filter: mbrtu.crc16.incorrect
CRC errors mean the frame was corrupted during transmission. Common causes:
| Cause | Fix |
|---|---|
| Electrical noise on RS-485 cable | Use shielded twisted pair. Route cable away from power cables. |
| Missing or wrong termination | Add 120Ω termination resistor at each end of the bus. |
| Baud rate mismatch | Verify all devices use the same baud rate. |
| Parity mismatch | Verify all devices use the same parity setting. |
| Cable too long | RS-485 supports up to 1200 m at 9600 baud. Reduce distance or lower baud rate. |
| Bad connector or loose wiring | Check all RS-485 connections and crimps. |
| A/B wires swapped | Some manufacturers label A/B differently. Try swapping. |
💡 Tip: If you see CRC errors only on responses from one specific slave, the problem is likely near that device — check its wiring and connectors.
13. Diagnosing Timing and Interframe Issues
Modbus RTU uses silence on the bus to detect frame boundaries. The standard requires 3.5 character times of silence between frames. At 9600 baud, this is approximately 4 ms.
Timing Problems in Wireshark
| Symptom | Cause | Fix |
|---|---|---|
| Frames split into two fragments | Interframe gap inside a frame (character delay too long) | Check RS-485 converter. Some USB adapters add latency. |
| Two frames merged into one | Interframe gap too short between request and response | Slave is responding too fast. Adjust interframe multiplier in WiresharkSerialAdapter settings. |
| Garbled or undecodable frames | Baud rate mismatch between adapter and bus | Verify baud rate matches exactly. |
Adjusting Interframe Settings
If frames are not being detected correctly, adjust the WiresharkSerialAdapter settings:
- Interframe Multiplier: Try increasing from 3.0 to 4.0 or 5.0 if frames are splitting
- Interframe Correction → Modbus CRC: This uses CRC validation to correct frame boundaries — recommended for most setups
14. Diagnosing Wrong Data Values
Filter: mbrtu.unit_id == <slave> && modbus.func_code == 3
Click on the response frame and check register values:
| Symptom | Cause | Fix |
|---|---|---|
| Register values correct in Wireshark but wrong in SCADA | SCADA data type or byte order wrong | Check UINT16 vs INT16 vs FLOAT32 and byte order in SCADA |
| Register values are 0 | Wrong register address | Check the zero-based offset (register 40001 = address 0) |
| Values change but do not match device display | Wrong scale factor in SCADA | Apply the correct scale factor from the register map |
For a full guide on register addressing, see: Modbus Register Map Explained
15. Alternative: Capturing Modbus RTU with a Python Script (Linux)
On Linux, an alternative to WiresharkSerialAdapter is a Python script that reads from the serial port and writes pcap data to a FIFO pipe that Wireshark reads.
Tools available on GitHub:
- ddmesh/modbus-rs485-wireshark-monitor — Python script using
pyserial, outputs to a FIFO pipe - Pinoccio/tool-serial-pcap — original serial-to-pcap tool
Basic Setup (Linux)
bash
pip install pyserial
python3 serial-pcap.py -b 19200 --fifo /tmp/wireshark
Then in Wireshark: Capture → Options → Manage Interfaces → Pipes → + → add /tmp/wireshark as a pipe.
Configure the DLT_User encapsulation table the same way as described in Section 6 (DLT 147 → mbrtu).
16. Common Modbus RTU Problems and What They Look Like in Wireshark
| Problem | Wireshark Symptom | Filter |
|---|---|---|
| Slave not responding | Query frames with no matching Response | mbrtu.unit_id == <addr> — check for responses |
| Wrong slave address | Responses from unexpected address | mbrtu.unit_id — check all Unit IDs |
| Address conflict | Two responses to one query | mbrtu.unit_id == <addr> — look for overlapping responses |
| CRC errors | Frames flagged with incorrect CRC | mbrtu.crc16.incorrect |
| Wrong register address | Exception code 02 in response | modbus.exception_code == 2 |
| Wrong function code | Exception code 01 in response | modbus.exception_code == 1 |
| Baud rate mismatch | No decodable frames or all CRC errors | Verify adapter baud rate matches bus |
| Parity mismatch | CRC errors on every frame | Verify adapter parity matches bus |
| Interframe timing | Frames split or merged incorrectly | Adjust interframe multiplier in adapter settings |
| Wrong data type in SCADA | Values correct in Wireshark but wrong in SCADA | Check data type and byte order in SCADA software |
Summary
Wireshark can capture Modbus RTU over RS-485 serial links using the free WiresharkSerialAdapter extension and a USB-to-RS-485 adapter.
The key setup steps:
- Install WiresharkSerialAdapter.exe in
C:\Program Files\Wireshark\extcap\wireshark - Configure the COM port — baud rate, parity, and stop bits must match the bus
- Set DLT 147 → mbrtu in Edit → Preferences → Protocols → DLT_USER
- Double-click the Serial Port Adapter to start capturing
The key filters:
- Use
mbrtuto see all Modbus RTU frames - Use
mbrtu.unit_id == <address>to filter by slave address - Use
mbrtu.crc16.incorrectto find CRC errors - Use
modbus.func_code,modbus.exception_code, andmodbus.reference_numfor application-layer analysis — these work the same as for Modbus TCP
💡 Tip: Use the free Modbus Frame Decoder Tool to decode any Modbus RTU frame byte by byte — including slave address, function code, register addresses, data values, and CRC-16 validation.
For Modbus TCP analysis, see: Wireshark for Modbus TCP: How to Capture, Filter, and Troubleshoot
