How to connect to a PLC from Python using OPC UA

Based on contributions by aashish.

OPC UA is a standardized industrial communication protocol. It lets a Python script read and write PLC variables directly by name, instead of sending raw strings or bytes over a socket and parsing them yourself. Use it when you want a laptop or PC script to monitor or control PLC variables in real time.

For a visual walkthrough of the setup alongside this guide, see this video.

What you need

  • A PLC with an OPC UA server. This guide sets one up with a PLC simulated in Codesys (Codesys Control Win V3 x64); the Python client code is the same regardless of which PLC brand is behind the OPC UA server.
  • Codesys development environment, to build/simulate the PLC program and enable its OPC UA server.
  • UaExpert — a free OPC UA client, used to browse the PLC’s variables and find their node IDs.
  • Python 3 with the opcua package: pip install opcua.
  • Your PC and the PLC on the same network (connected via a network switch).

:warning: Check: this was demonstrated with a PLC simulated in Codesys, not a real Siemens PLC in TIA Portal. An S7-1500 has a built-in OPC UA server that you enable in the CPU’s device properties in TIA Portal instead of through Codesys — that TIA Portal-side setup isn’t covered here. Once the OPC UA server is running, the UaExpert and Python steps below are the same.

Steps

1. Create the variables in the PLC program

In a new Codesys standard project, select Codesys Control Win V3 x64 as the device and write the PLC program in Structured Text (ST). Declare the variables you want to expose, for example:

VAR
    Xhoek : INT;
    Yhoek : INT;
END_VAR

2. Enable OPC UA symbol export

In the project tree, right-click Application and add a Symbol Configuration. Make sure Support OPC UA features is checked.

Open the Symbol Configuration page and click Build. This generates a list of program symbols (e.g. PLC_PRG) — open the one for your program and select the variables you want to be readable/writable over OPC UA. Click Build again to apply.

3. Start the PLC

Make sure the Codesys Gateway and Codesys Control Win are running (check the Windows taskbar status area; search for “Codesys” in Windows search if you don’t see the icon). Then click Login and Start in Codesys to bring the simulated PLC online.

4. Find the node IDs with UaExpert

Open UaExpert, click the + icon, and on the advanced page add this as the endpoint URL:

opc.tcp://localhost:4840

Click OK, then Connect to the server. Once connected, browse to your program in the address space tree to see all variables exposed over OPC UA.

Copy the node ID of a variable. It will look like:

NS4|String|var|CODESYS Control Win V3 x64.Application.PLC_PRG.Xhoek

Remove the part before |var| and replace it with ns=4;s=, giving:

ns=4;s=|var|CODESYS Control Win V3 x64.Application.PLC_PRG.Xhoek

You’ll use strings like this as node IDs in the Python script.

5. Write the Python client

Install the client library:

pip install opcua
from opcua import Client, ua
import time

# Endpoint URL — if "localhost" doesn't work (e.g. connecting from another PC), use the PLC's IP address
url = "opc.tcp://localhost:4840"
client = Client(url)

try:
    client.connect()
    print("Connected to OPC UA Server")

    x_node = client.get_node("ns=4;s=|var|CODESYS Control Win V3 x64.Application.PLC_PRG.Xhoek")
    y_node = client.get_node("ns=4;s=|var|CODESYS Control Win V3 x64.Application.PLC_PRG.Yhoek")

    print("Current values:")
    print(f"Xhoek: {x_node.get_value()}")
    print(f"Yhoek: {y_node.get_value()}")

    while True:
        x_value = 123
        y_value = 456
        x_node.set_value(x_value, ua.VariantType.Int16)
        y_node.set_value(y_value, ua.VariantType.Int16)
        print(f"Sent to PLC -> X: {x_node.get_value()}, Y: {y_node.get_value()}")
        time.sleep(0.5)

except Exception as e:
    print(f"Error: {e}")

finally:
    client.disconnect()
    print("Disconnected from OPC UA Server")

Replace x_value/y_value with your own logic — this example just shows how to push values to the PLC. Running it, you should see Xhoek and Yhoek change live in UaExpert or on the PLC.

Troubleshooting

  • If the client can’t connect and you’re not running the script on the same machine as the PLC/server, change localhost in both the OPC UA server endpoint and the Python url variable to the PLC’s actual IP address.
  • The opcua package (also known as python-opcua / freeopcua) is a widely-used but no longer actively maintained library. If you run into compatibility issues, the actively maintained successor is asyncua (pip install asyncua), which also offers a synchronous client API.

Related


Rewritten and consolidated (Sept 2026) from the original student how-to’s: How to use and code with OPC UA Protocol:.