Based on contributions by How-to.
Snap7 is an open-source library that lets a Python script read and write data blocks on a Siemens S7 PLC directly, without you having to build your own communication protocol. Use it when you want a laptop or PC application to monitor or control PLC variables in real time.
What you need
- A Siemens PLC (S7-1200/S7-1500 family) programmed in TIA Portal, with a data block (DB) you want to read or write.
- Full access to the TIA Portal project so you can change protection settings and download to the PLC.
- Python 3 with the
python-snap7package. - Your PC and the PLC on the same network.
Steps
1. Allow PUT/GET communication on the PLC
In TIA Portal, open the PLC’s device properties and go to Protection & Security. Set Access Level to Full Access and enable PUT/GET Communication from remote partner.
2. Turn off optimized block access on the data block
Right-click the data block (DB) you want to reach from Python and open Properties. Under Attributes, uncheck Optimized block access. Snap7 needs fixed byte offsets, which optimized blocks don’t expose.
3. Compile and download the project
Compile the project. If optimized block access is off, you’ll see a fixed Offset column next to each variable in the DB — note these down, you’ll need them from Python. Then download the project to the PLC.
4. Install the Snap7 library
pip install python-snap7
python-snap7 is a Python wrapper around the Snap7 C library. The three functions you’ll use most:
- Connect — opens a connection to the PLC using its IP address and rack/slot number.
- Read — reads raw bytes from a DB (or input/output/marker area) at a given address.
- Write — writes raw bytes back to the PLC.
5. Connect and read/write a boolean
import logging
import snap7
from snap7.util import get_bool, set_bool
class SiemensPlc:
def __init__(self):
self.plc = None
self.connected = False
self.logger = logging.getLogger(__name__)
def connect(self, ip="192.168.0.99", rack=0, slot=1):
try:
self.plc = snap7.client.Client()
self.plc.connect(ip, rack, slot) # adjust the IP and rack/slot to match your PLC
self.connected = True
except RuntimeError as e:
self.logger.error(f"Error connecting to PLC: {e}")
def disconnect(self):
if self.plc is not None:
self.plc.disconnect()
self.connected = False
def read_bool(self, db_number, start, byte_offset, bit_offset):
"""Read a single boolean from a DB, at DB address (start + byte_offset), bit bit_offset."""
address = start + byte_offset
data = self.plc.db_read(db_number, address, 1) # read one byte
return get_bool(data, 0, bit_offset)
def write_bool(self, db_number, start, byte_offset, bit_offset, value):
"""Write a single boolean to a DB, at DB address (start + byte_offset), bit bit_offset."""
address = start + byte_offset
data = self.plc.db_read(db_number, address, 1) # read the byte first
set_bool(data, 0, bit_offset, value) # modify the bit in place
self.plc.db_write(db_number, address, data) # write the modified byte back
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
plc = SiemensPlc()
plc.connect()
if plc.connected:
value = plc.read_bool(db_number=1, start=0, byte_offset=0, bit_offset=0)
print(f"Current value: {value}")
plc.write_bool(db_number=1, start=0, byte_offset=0, bit_offset=0, value=True)
plc.disconnect()
Adjust db_number, start, byte_offset and bit_offset to match the offsets you noted from the compiled DB in step 3.
Check: the address math in
read_bool/write_bool(reading only the byte atstart + byte_offset) was adjusted from the original source to avoid an out-of-range read whenbyte_offset > 0. Verify against your own DB layout before relying on it.
Related
- How to connect to a PLC from Python using OPC UA — connecting to a PLC with OPC UA instead of Snap7
Rewritten and consolidated (Sept 2026) from the original student how-to’s: Connect a computer to a Siemens PLC using the Snap7 library in Python.


