S7comm Protocol Explained: How Siemens S7 PLCs Communicate

By | May 14, 2026

If you have ever opened Wireshark on a network with Siemens PLCs, you have seen S7comm. It is the language Siemens controllers use to talk to TIA Portal, to WinCC, to SCADA front-ends, and to each other. The protocol has been around since 1994 and it is still the default way to move data in and out of S7-300, S7-400, S7-1200 and S7-1500 controllers.

This article is a working engineer’s guide. No theory for the sake of theory. Just what S7comm is, how the frame is built, what the function codes mean, and what to check first when something does not work.

What is S7comm in one paragraph

S7comm (S7 Communication) is a proprietary Siemens protocol that rides on top of ISO-on-TCP (RFC 1006) using TCP port 102. It is not an open standard. Most of what the industry knows about it comes from open-source projects like Snap7, the Wireshark dissector, and libnodave. It is used for three jobs: programming the PLC, reading and writing data, and diagnostics. On newer S7-1200 and S7-1500 controllers, Siemens introduced an encrypted variant called S7CommPlus, which uses protocol ID 0x72 instead of 0x32.

Where S7comm sits in the stack

S7comm is not a flat protocol. It is wrapped inside two other layers before it touches TCP. Understanding this stack saves hours of debugging:

LayerProtocolJob
7 — ApplicationS7commActual read/write/program commands
6 — PresentationCOTP (ISO 8073)Connection-oriented transport, TSAP addressing
5 — SessionTPKT (RFC 1006)Wraps ISO traffic in TCP packets
4 — TransportTCPPort 102
3 — NetworkIP

So when you capture S7 traffic, Wireshark shows you the layers in this order: Ethernet → IP → TCP → TPKT → COTP → S7comm. If any one of those layers fails, the connection drops. Most “S7 not connecting” issues are actually COTP-level — a wrong TSAP or a closed port 102.

Port 102 and the IEC 61850 conflict

Port 102 is the standard TCP port for ISO-TSAP Class 0. Siemens uses it for every S7 product. But here is the catch: IEC 61850 MMS also runs on port 102. If you run an IEC 61850 server on a machine that also has SIMATIC software listening, one of them will refuse to start. You will see a “port already in use” error.

Quick fix on Windows: open a command prompt and run netstat -a -b to find which process owns 102. Usually it is the Siemens SIMATIC service. Stop it before launching tools like IEDScout. For more on this overlap, see our guide on IEC 61850 MMS and TCP port 102.

How a connection gets established

S7comm needs three steps before any data moves. Skip one and nothing works.

  1. TCP handshake on port 102. Normal SYN, SYN-ACK, ACK. Standard stuff.
  2. COTP Connect Request. The client sends a TSAP pair. The source TSAP is usually 0x0100 (PG/programming). The destination TSAP encodes the connection type and the rack/slot of the CPU. First byte: 0x01 for PG, 0x02 for OP (HMI). Second byte: rack number in the upper nibble, slot number in the lower nibble. For an S7-1200, this is typically 0x0102 (rack 0, slot 2).
  3. S7comm Setup Communication. Function code 0xF0. Both sides negotiate the max PDU size and how many parallel jobs they will allow without acknowledgment. Typical PDU sizes are 240, 480, or 960 bytes.

Only after step three can the master start sending read or write requests.

The S7comm PDU header

Once communication is set up, every S7comm message carries a header that is either 10 or 12 bytes. The 12-byte version is used for Ack_Data responses because it carries two extra error bytes. Here is what each field does:

FieldSizeWhat it does
Protocol ID1 byteAlways 0x32 for S7comm. 0x72 means S7CommPlus.
Message Type (ROSCTR)1 byte0x01 Job, 0x02 Ack, 0x03 Ack_Data, 0x07 Userdata
Reserved2 bytesAlways 0x0000. Ignored on receive.
PDU Reference2 bytesMaster-generated counter. Used to match a response to a request. Little-endian.
Parameter Length2 bytesSize of the parameter field. Big-endian.
Data Length2 bytesSize of the data field. Big-endian.
Error Class1 byteOnly in Ack_Data. 0x00 means no error.
Error Code1 byteOnly in Ack_Data. Specific error reason.

Notice the mixed endianness. PDU Reference is little-endian. Parameter and Data Length are big-endian. This trips up a lot of people writing their own parsers.

Message types (ROSCTR)

The Message Type byte — also called ROSCTR (Remote Operating Service Control) — tells you what kind of PDU you are looking at. There are only four valid values:

  • 0x01 Job — A request from the master. Read data, write data, start CPU, stop CPU, upload program.
  • 0x02 Ack — A bare acknowledgment with no data. Rarely seen in S7-300/400 traffic.
  • 0x03 Ack_Data — Acknowledgment with a payload. This is what the PLC sends back for almost every Job request.
  • 0x07 Userdata — An extension. Carries SZL reads, time sync, security functions, cyclic reads, and alarm acknowledgments. Has a different parameter structure.

Function codes you will actually see

Inside Job and Ack_Data PDUs, the parameter field starts with a function code. This byte decides what the PLC will do. Here are the ones that matter in the field:

CodeFunctionWhat it does
0xF0Setup CommunicationThe first message after COTP connect. Negotiates PDU size and Ack queue length.
0x04Read VariableThe bread-and-butter read. Pulls values from DB, I, Q, M, T, C areas.
0x05Write VariableWrites values into the same areas. Returns a per-item status byte.
0x1ARequest DownloadBegin sending a program block from PG to PLC.
0x1BDownload BlockThe actual program data chunks.
0x1CDownload EndedTells the PLC the download is finished.
0x1D / 0x1E / 0x1FUpload (Start / Block / End)Reading the PLC program back into Step 7 or TIA.
0x28PI ServiceProgram Invocation — used to start or restart the CPU.
0x29PLC StopStops the CPU. Yes, this exists. Yes, it works over the network with no authentication on older PLCs.

The last few codes are why S7comm gets flagged by ICS security tools like Dragos and Claroty. On an S7-300 or S7-400, any device that can reach port 102 can issue a Stop CPU command. The protocol has no built-in authentication. The PLC password, when enabled, is exchanged in clear text in the Userdata function. This is one of the main reasons Siemens introduced S7CommPlus.

How addressing works

When you do a Read Variable (0x04), you build a Request Item that points to a specific spot in PLC memory. There are three addressing modes:

  • Any-type addressing — The default for S7-300/400. You specify the memory area (DB, I, Q, M, T, C), the address, and the data type. This is what libnodave and Snap7 use by default.
  • DB-type addressing — A more compact form for data blocks specifically.
  • Symbolic addressing — Used by S7-1200 and S7-1500 only. You address variables by their tag name instead of an offset. Rarely used in practice because it requires Symbol Server access.

The memory area is identified by a single byte:

CodeAreaMeaning
0x81IProcess Inputs
0x82QProcess Outputs
0x83MFlags / Merkers
0x84DBData Blocks
0x85DIInstance DB
0x86LLocal data (should not be exposed over network)
0x1CCCounters
0x1DTTimers

S7comm vs S7CommPlus

Siemens introduced S7CommPlus around the S7-1200 V4 firmware. The big differences:

  • Protocol ID is 0x72, not 0x32.
  • Encryption. S7CommPlus encrypts the payload. The exact scheme is undocumented but has been reverse-engineered.
  • Integrity check. Each message carries an integrity hash, which makes replay attacks much harder.
  • Anti-replay. Session keys make recorded traffic unusable.

If you need to read or write data from a modern PLC and your tooling does not speak S7CommPlus, you have two options. First, in TIA Portal, enable “Permit access with PUT/GET communication from remote partner” under the CPU’s protection settings. This forces the PLC to also accept legacy S7comm. Second, switch to a documented protocol — OPC UA on S7-1500 works very well and avoids the proprietary mess entirely. See our guide on connecting any PLC to OPC UA.

Capturing S7comm in Wireshark

Wireshark has a built-in S7comm dissector. It works out of the box for the classic 0x32 protocol. A few practical filters:

  • tcp.port == 102 — Catches everything on the S7 port, including the COTP and TPKT layers.
  • s7comm — Shows only frames that the dissector successfully parses as S7.
  • s7comm.header.rosctr == 1 — Only Job requests.
  • s7comm.param.func == 0x05 — Only Write Variable. Useful when you suspect an unauthorized write.
  • s7comm.param.func == 0x29 — PLC Stop commands. Anything matching this on a production network is worth investigating immediately.

If you are testing without a real PLC, Snap7 ships a free server simulator. You can run it on your laptop and point TIA Portal or any S7 client at it.

Common problems and what they actually mean

Most S7comm errors are not really S7comm errors. They are COTP or firewall issues misreported by the client software.

SymptomLikely causeWhat to check
Cannot connect at allPort 102 blocked or PLC unreachablePing the PLC, then telnet <ip> 102. If telnet fails, it is a network problem.
TCP connects but COTP rejectsWrong TSAP — wrong rack or slotS7-300 is usually rack 0, slot 2. S7-1500 is rack 0, slot 1. Check the hardware config.
Read returns 0x03 (Access not allowed)PUT/GET disabledIn TIA Portal, enable PUT/GET in the CPU properties under Protection & Security.
Read returns 0x05 (Address out of range)You asked for a DB that does not exist or an offset past the end of the DBVerify the DB number and the actual size of the block in TIA.
Random disconnects after minutesIdle timeout or TCP keepalive missingSend a dummy read every 30 seconds, or enable TCP keepalive in your client library.
Works for HMI but not for custom codeWrong source TSAP (you used PG instead of OP, or vice versa)For OP/HMI traffic, use source TSAP 0x0200 instead of 0x0100.

Libraries for talking S7

You almost never want to write S7comm from scratch. These libraries already handle the COTP and TPKT layers and expose a clean API:

  • Snap7 — Open source, C/C++ core with bindings for Python (python-snap7), C#, Java, and Node.js. Free for commercial use. Works with S7-200, S7-300, S7-400, S7-1200, S7-1500 and LOGO.
  • Sharp7 — A pure C# port of Snap7. No native DLL needed. Useful for .NET projects on non-Windows targets.
  • libnodave — Older C library. Still works but the project is mostly dormant. Snap7 superseded it.
  • plc4x — Apache project. Wraps multiple PLC protocols including S7 behind a single interface. Good if your code needs to support Allen-Bradley and Siemens at the same time.

Should you still use S7comm in new designs?

Honest answer: only if you have to. For a brownfield site full of S7-300 and S7-400 PLCs, you have no choice. The protocol works and there are mature tools.

For new designs on S7-1500 hardware, OPC UA is the better path. It is standardized, encrypted by default, and Siemens has invested heavily in making the on-board OPC UA server perform well. You get documented behavior, certificate-based auth, and no port 102 conflicts with IEC 61850 in mixed substations.

That said, S7comm is not going away. Too many controllers in the field speak only this protocol, and the engineering software still defaults to it. Knowing how the frame is built is part of the job.

Frequently asked questions

Is S7comm the same as Profinet?

No. Profinet is a real-time Ethernet protocol used between the CPU and field devices like distributed I/O, drives, and remote stations. S7comm is what TIA Portal, WinCC and other higher-level tools use to talk to the CPU itself. A Siemens PLC will speak both at the same time.

What port does S7comm use?

TCP port 102. This is the ISO-TSAP Class 0 port and it is shared with IEC 61850 MMS.

Can S7comm work over Profibus or MPI?

Yes. S7comm is transport-agnostic. It runs over Industrial Ethernet (most common today), Profibus, and MPI. The application-layer behavior is identical. Only the lower layers change.

Is S7comm encrypted?

No. Classic S7comm (protocol ID 0x32) sends everything in clear text, including the PLC password. S7CommPlus (protocol ID 0x72) on newer PLCs adds encryption and integrity checks.

How do I stop someone from sending a PLC Stop command over the network?

Network segmentation. Put the PLC behind a firewall that only allows port 102 traffic from authorized engineering stations. On S7-1200/1500, also set a CPU password and enable “Full protection” or “Read-only access” under the CPU’s Protection settings. These controls are described in IEC 62443 Foundational Requirements.

Why does my S7-1500 reject S7comm reads from my custom application?

Because PUT/GET is disabled by default. Open the CPU properties in TIA Portal, go to Protection & Security → Connection mechanisms, and tick “Permit access with PUT/GET communication from remote partner”. Rebuild the project completely (Software → Rebuild all) and download. A partial compile is not enough.

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.