Wireshark for Modbus TCP: How to Capture, Filter, and Troubleshoot

By | April 10, 2026

Modbus TCP is one of the easiest protocols to analyze in Wireshark. It runs on TCP port 502, uses a simple request/response pattern, and Wireshark decodes every field — MBAP header, function code, register addresses, and data values — in plain text.

But engineers still struggle with three things: finding the right display filters, understanding what a healthy vs broken Modbus conversation looks like, and diagnosing why a device is not responding.

This guide covers everything: capture setup, display filters verified against the official Wireshark reference, how to read decoded Modbus packets, and how to diagnose the 10 most common Modbus TCP problems using Wireshark.

1. How Modbus TCP Appears in Wireshark

Wireshark decodes Modbus TCP as two protocol layers:

LayerProtocol NameWhat It Shows
Modbus/TCP (mbtcp)MBAP headerTransaction ID, Protocol ID, Length, Unit ID
Modbus (modbus)Application dataFunction code, register addresses, data values, exception codes

The Info column shows a summary like:

Query: Trans: 1; Unit: 1, Func: 3: Read Holding Registers
Response: Trans: 1; Unit: 1, Func: 3: Read Holding Registers

This tells you the transaction ID, the Unit ID (slave address), the function code, and whether it is a request (Query) or response (Response).

2. How to Capture Modbus TCP Traffic

Capture Filter (Before Starting Capture)

To capture only Modbus TCP traffic:

tcp port 502

This reduces file size and makes analysis faster.

Where to Capture

LocationWhen to Use
On the SCADA server or PLCBest view of all Modbus communication from the master
On the Modbus deviceOnly if the device supports packet capture
On a network switch (port mirroring)When you cannot install Wireshark on the SCADA server
On a network TAPFor non-intrusive capture between master and slave

Start Capture

  1. Open Wireshark → select the network interface connected to the Modbus network
  2. Enter the capture filter tcp port 502
  3. Click Start
  4. Let it run for at least one full poll cycle (usually 5–30 seconds)
  5. Stop the capture and save the file

3. Decoding Modbus on Non-Standard Ports

Wireshark only decodes Modbus automatically on port 502. If your device uses a different port (e.g., 1502, 5020, 8502), Modbus packets will appear as raw TCP data.

Fix: Use “Decode As”

  1. Right-click on a packet that should be Modbus
  2. Select Decode As…
  3. In the table, set: Field = TCP port, Value = your port number, Current = MBTCP
  4. Click OK

Now Wireshark decodes all traffic on that port as Modbus TCP.

Fix: Change Preferences

  1. Go to Edit → Preferences → Protocols → Modbus/TCP
  2. Change the Modbus TCP Port value to your custom port
  3. Click OK

4. Display Filters for Modbus TCP

Wireshark Modbus TCP Analysis

All filter field names verified against the official Wireshark Display Filter Reference: modbus and mbtcp.

Basic Filters

FilterWhat It Shows
modbusAll Modbus traffic (requests + responses)
mbtcpAll Modbus/TCP MBAP headers
tcp.port == 502All traffic on port 502 (including TCP handshake)
tcp.dstport == 502Only requests sent to Modbus servers
tcp.srcport == 502Only responses from Modbus servers

Function Code Filters

FilterWhat It Shows
modbus.func_code == 3Read Holding Registers (FC 03)
modbus.func_code == 4Read Input Registers (FC 04)
modbus.func_code == 6Write Single Register (FC 06)
modbus.func_code == 16Write Multiple Registers (FC 16)
modbus.func_code == 1Read Coils (FC 01)
modbus.func_code == 5Write Single Coil (FC 05)
modbus.func_code >= 128All exception responses (FC + 0x80)

MBAP Header Filters

FilterWhat It Shows
mbtcp.trans_idFilter by Transaction ID
mbtcp.prot_idProtocol ID (always 0 for Modbus)
mbtcp.lenMBAP Length field
mbtcp.unit_idUnit ID (slave address)
mbtcp.unit_id == 1Only traffic to/from Unit ID 1

Data and Register Filters

FilterWhat It Shows
modbus.reference_numRegister address (starting address)
modbus.reference_num == 100Requests targeting register 100
modbus.word_cntNumber of registers requested
modbus.byte_cntByte count in response
modbus.dataRaw data bytes in response
modbus.exception_codeException code in error responses
modbus.exception_code == 2Illegal Data Address exceptions only

Combination Examples

Traffic to a specific device:

modbus && ip.addr == 192.168.1.100

Only exception responses from any device:

modbus.func_code >= 128

Only FC 03 requests to Unit ID 5:

modbus.func_code == 3 && mbtcp.unit_id == 5

Slow responses (gap > 1 second):

modbus && frame.time_delta > 1

5. How to Read a Decoded Modbus Packet

Click on a Modbus packet in Wireshark. The packet detail pane shows two sections:

Modbus/TCP Section (MBAP Header)

Modbus/TCP
    Transaction Identifier: 1
    Protocol Identifier: 0
    Length: 6
    Unit Identifier: 1

Modbus Section (PDU)

For a Read Holding Registers request:

Modbus
    Function Code: Read Holding Registers (3)
    Reference Number: 100
    Word Count: 10

For the response:

Modbus
    Function Code: Read Holding Registers (3)
    Byte Count: 20
    Register 100 (UINT16): 2301
    Register 101 (UINT16): 2295
    Register 102 (UINT16): 2310
    ...

Wireshark automatically matches each Transaction ID in the request to the corresponding response. You can see the matched pair by looking at the Transaction Identifier.

6. What a Healthy Modbus Conversation Looks Like

A healthy Modbus TCP session shows this pattern:

#DirectionInfo
1Client → ServerTCP SYN
2Server → ClientTCP SYN-ACK
3Client → ServerTCP ACK
4Client → ServerQuery: Trans: 1; Unit: 1, Func: 3: Read Holding Registers
5Server → ClientResponse: Trans: 1; Unit: 1, Func: 3: Read Holding Registers
6Client → ServerQuery: Trans: 2; Unit: 1, Func: 3: Read Holding Registers
7Server → ClientResponse: Trans: 2; Unit: 1, Func: 3: Read Holding Registers
… repeats every poll cycle

Key signs of healthy communication:

  • Every Query has a matching Response with the same Transaction ID
  • Transaction IDs increment sequentially (1, 2, 3, …)
  • Response follows request within milliseconds (typically < 100 ms)
  • No TCP retransmissions
  • No exception responses

7. Diagnosing No Response from a Device

Symptom: SCADA shows “Timeout” or “No response.” Wireshark shows the request but no response.

What to Look For

Filter: modbus && ip.addr == <device IP>

What You SeeCauseFix
Query sent, no Response packetDevice is not reachable or not listeningPing the device. Check cable. Verify port 502 is open.
TCP SYN sent, no SYN-ACKDevice is offline or firewall blocks port 502Check power. Check firewall rules.
TCP SYN-ACK received, then Query sent, no ResponseDevice accepts TCP but Modbus service is not runningEnable Modbus TCP in device configuration.
Query sent, TCP RST receivedDevice actively refused the connectionModbus service disabled, or max connections exceeded.

Quick Check

Filter for TCP problems:

tcp.analysis.retransmission && tcp.port == 502

If you see retransmissions, the network is losing packets or the device is not responding.

8. Diagnosing Exception Responses

Symptom: SCADA shows an error code. Wireshark shows a Response with function code ≥ 128.

Filter: modbus.func_code >= 128

Or filter by specific exception code: modbus.exception_code == 2

Exception CodeNameMeaningCommon Cause
01Illegal FunctionDevice does not support this FCUsing FC 04 on a device that only supports FC 03
02Illegal Data AddressRegister does not existWrong register address, off-by-one error
03Illegal Data ValueValue out of rangeWriting 0x0001 to a coil (must be 0xFF00)
04Slave Device FailureInternal device errorHardware fault in the device
06Slave Device BusyDevice is processing another requestToo many requests too fast. Slow down poll rate.

Exception 02 (Illegal Data Address) is the most common. It usually means the register address in the request does not match the device’s register map. Check the zero-based offset — register 40001 = PDU address 0x0000.

For a full guide, see: Modbus Function Codes Explained

9. Diagnosing Slow Responses and Timeouts

Symptom: SCADA reads data but values update slowly, or occasional timeouts occur.

Measure Response Time

Add a custom column: right-click column header → Column Preferences → add frame.time_delta_displayed as “Delta Time.”

Now you can see the time between each packet. A healthy response arrives within 10–100 ms. If responses take 500 ms or more, something is wrong.

Filter for Slow Responses

modbus && frame.time_delta > 0.5

Common Causes

Symptom in WiresharkCauseFix
Response takes > 500 msDevice overloaded with too many requestsReduce poll rate. Read registers in larger blocks.
Response takes > 1 secondNetwork congestionCheck network load. Move Modbus devices to a dedicated VLAN.
Occasional timeouts between normal responsesConnection limit exceeded — another client is competingReduce the number of Modbus clients connected to the device.
Increasing delay over timeDevice memory leak or resource exhaustionPower cycle the device. Update firmware.

10. Diagnosing Wrong Data Values

Symptom: SCADA shows unexpected values — 0, garbage, or values that do not match the device display.

What to Check in Wireshark

  1. Filter: modbus.func_code == 3 (or the FC you are using)
  2. Click on the Response packet
  3. Expand the Modbus section → look at the register values
SymptomCauseFix
Register values are correct in Wireshark but wrong in SCADASCADA data type or byte order misconfiguredCheck UINT16 vs INT16 vs FLOAT32 in SCADA. Check byte order.
Register values are 0 in WiresharkWrong register address — you are reading empty registersCheck the device register map. Fix the zero-based offset.
Register values change but do not match the device displayWrong scale factor in SCADAApply the correct scale factor from the register map.
Two registers show random-looking numbers32-bit float with wrong byte orderSwap the two registers (try AB CD vs CD AB).

For a full guide on register addressing, see: Modbus Register Map Explained

11. Diagnosing Connection Drops

Symptom: Communication works for a while, then drops. SCADA reconnects after a few seconds.

What to Look For

Filter: tcp.flags.reset == 1 && tcp.port == 502

This shows all TCP RST (reset) packets on port 502. A RST means one side forcibly closed the connection.

PatternCauseFix
Device sends RST after a period of inactivityDevice idle timeout is shorter than the SCADA poll intervalReduce idle timeout on device, or poll more frequently.
Device sends RST when a new client connectsMax connections exceeded — device drops the oldestReduce the number of SCADA clients. Use a single master.
Client sends RST after timeoutSCADA timed out waiting for a responseCheck device health. Check network path.
Periodic RST every N minutesFirewall connection timeout closing idle sessionsEnable TCP keep-alive on the SCADA side.

Also check: tcp.analysis.retransmission && tcp.port == 502 for packet loss.

12. Diagnosing Overlapping Requests

Symptom: Transaction IDs are mismatched. Responses do not match requests.

The Problem

Some Modbus clients send a new request before the previous response arrives. If the Transaction IDs get out of sync, responses are matched to the wrong requests.

What to Look For

Filter: modbus and sort by Transaction ID.

Look for:

  • Two Queries with different Transaction IDs before any Response arrives — the client is sending requests too fast
  • Response Transaction ID does not match the last Query — responses are out of order

Fix

Configure the SCADA master to wait for each response before sending the next request. Or enable the TCP reassembly option in Wireshark: Edit → Preferences → Protocols → Modbus/TCP → Desegment all Modbus RTU packets spanning multiple TCP segments.

13. Useful Wireshark Columns for Modbus Analysis

Add these custom columns for faster troubleshooting:

Column TitleTypeField Name
Transaction IDCustommbtcp.trans_id
Unit IDCustommbtcp.unit_id
Function CodeCustommodbus.func_code
Register AddressCustommodbus.reference_num
Delta TimeCustomframe.time_delta_displayed
Source IPNormalip.src
Destination IPNormalip.dst

To add: right-click any column header → Column Preferences → click + → set the Title and Field name.

With these columns, you can see the Transaction ID, Unit ID, FC, register address, and response time for every packet — without clicking on each one.

14. Common Modbus TCP Problems and What They Look Like in Wireshark

ProblemWireshark SymptomFilter to Use
Device offlineTCP SYN with no SYN-ACKtcp.flags.syn == 1 && tcp.port == 502
Firewall blockingTCP RST immediately after SYNtcp.flags.reset == 1 && tcp.port == 502
Wrong Unit IDQuery sent, no Modbus response (device ignores wrong Unit ID)mbtcp.unit_id — check if ID matches device
Wrong register addressException code 02 in responsemodbus.exception_code == 2
Wrong function codeException code 01 in responsemodbus.exception_code == 1
Device overloadedLong delays between request and responsemodbus && frame.time_delta > 1
Connection limit exceededTCP RST when connectingtcp.flags.reset == 1 && tcp.port == 502
Packet lossTCP retransmissionstcp.analysis.retransmission && tcp.port == 502
Wrong data valuesCorrect register values in Wireshark but wrong in SCADACheck data type and byte order in SCADA
Overlapping requestsTransaction IDs out of ordermodbus — check Transaction ID sequence

Summary

Wireshark makes Modbus TCP problems visible. Every request, every response, every exception, and every timing issue is captured and decoded.

The key things to remember:

  • Use modbus as the main display filter
  • Use modbus.func_code >= 128 to find all exception responses
  • Use modbus.exception_code == 2 for the most common error (wrong register address)
  • Use frame.time_delta to measure response times and find slow devices
  • Use tcp.analysis.retransmission to find packet loss
  • Use tcp.flags.reset to find connection drops
  • If Modbus is on a non-standard port, use Decode As → MBTCP
  • Add custom columns for Transaction ID, Unit ID, and Function Code to speed up analysis

💡 Tip: Use the free Modbus Frame Decoder Tool to decode any Modbus frame byte by byte — including MBAP header, function code, register addresses, and CRC validation.

Author: Zakaria El Intissar

I'm an automation and industrial computing engineer with 12 years of experience in power system automation, SCADA communication protocols, and electrical protection. I build tools and write guides for Modbus, DNP3, IEC 101/103/104, and IEC 61850 on ScadaProtocols.com to help engineers decode, analyze, and troubleshoot real industrial communication systems.

Leave a Reply

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