Based on contributions by Ihsan, pauladelahoz, Thanusan_Thurairajah, Dave_Vermeulen, How-to.
Use this method when you want to exchange data between a Python program on your PC and a UR robot — for example sending coordinates from a vision script, or sending simple commands and reading back sensor values — without installing the RTDE library. It works by opening a plain TCP socket between the robot controller and your PC.
What you need
- A UR robot and a PC on the same network, see How to find and set the IP address for connecting a PC to a UR robot to find/set the IP addresses
- Python 3 (only the standard library
socketandstructmodules are needed) - Access to the teach pendant to load a URScript program
Steps
1. Choose an IP address and a port
You already need an IP address for the robot and your PC (see How to find and set the IP address for connecting a PC to a UR robot). You also need a port number: a number between 0 and 65535 that identifies a specific service on that IP address.
- Ports 0–1023 are reserved for common protocols (HTTP, HTTPS, FTP, SSH, …) — don’t use these.
- Ports 1024–49151 are registered/assigned ports (IANA).
- Ports 49151–65535 are free for temporary/private use — the best range to pick a port for your own robot communication.
2. Decide which side is the TCP server
Either side can act as the server (the one that binds and listens for a connection) and either side can be the client (the one that connects out). Most examples in these how-tos use the PC as the server and the robot as the client, since it’s simpler to set up from URScript with socket_open.
3. Set up the Python side (server)
import socket
HOST = "192.168.0.185" # your PC's IP address
PORT = 5000 # must match the port used by the robot
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT)) # port can be anything above 1024, as long as no other process is using it
server_socket.listen(5)
print("Server is listening for connections...")
while True:
client_socket, address = server_socket.accept()
print(f"Connection from {address} has been established!")
while True:
msg = client_socket.recv(1024)
if not msg:
break
print(msg.decode("utf-8"))
message_to_send = "(1.2, 1.3, 1.4)"
client_socket.sendall(bytes(message_to_send, "ascii"))
client_socket.close()
4. Set up the robot side (URScript client)
port = 5000
ip = "192.168.78.1" # your PC's IP address
socket_name = "anything"
socket_open(ip, port, socket_name)
while True:
# receive the expected 3 floating point values
receive = socket_read_ascii_float(3, socket_name)
textmsg(receive)
# send a message back
socket_send_string("Send your strings here", socket_name)
end
socket_close(socket_name)
Place
socket_openandsocket_closeoutside the main program loop — opening the connection on every loop iteration causes performance issues and can overload the network.
5. Send different data types from the robot
The robot has dedicated functions to send single values of different types:
byte_value = 1
socket_send_byte(byte_value) # send a single byte (0-255)
socket_send_int(2) # send an integer
socket_send_string("hello") # send a string
6. Read those values on the Python side
import struct
# Read one byte sent with socket_send_byte
data = client_socket.recv(1)
byte_values = struct.unpack('1B', data)
print(f"Received byte: {byte_values[0]}")
7. Send a list of numbers from Python to the robot
To send a list of integers as raw bytes:
import struct
def send_data(sock, data_list):
try:
byte_data = struct.pack(f'{len(data_list)}B', *data_list)
sock.sendall(byte_data)
print(f"List sent to the robot: {data_list}")
except Exception as e:
print(f"Error sending data: {e}")
data_list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
send_data(client_socket, data_list)
To send a list of floats, encode them as a comma-separated ASCII string instead:
def send_floats(sock, data_list):
float_str = ",".join(str(f) for f in data_list)
sock.sendall(float_str.encode('ascii'))
8. Read a list of numbers on the robot
socket_open("192.168.0.185", 30000)
# Only works if the incoming values are integers
integers = socket_read_byte_list(10) # adjust the count to the size of the array sent
# Use this if the incoming values are floats, sent as e.g. "(1.2, 1.3, 1.4)"
floats = socket_read_ascii_float(10) # adjust the count to the size of the array sent
textmsg("Integer value on position 1: ", integers[1])
textmsg("Float value on position 1: ", floats[1])
The float string must be a parenthesized, comma-separated list, e.g. (1.2, 1.3, 1.4). If a read fails, the first element of the returned list is 0, followed by -1 for socket_read_byte_list or nan (“Not a Number”) for socket_read_ascii_float.
9. Worked example: receiving and parsing an “X,Y,Z” string
Some servers (e.g. a vision script) don’t send fixed-size numeric arrays but a single line of text like "-0.45,0.375,0.25". Read it with socket_read_line and parse it manually:
# Constants
SOCKET_HOST = "192.168.0.10" # IP address of the external vision server (usually your PC)
SOCKET_PORT = 30020
SOCKET_NAME = "vision_socket"
RESPONSE_TIMEOUT = 0.5 # seconds to wait for a response
# Open the connection once, at the start of the program
socket_open(SOCKET_HOST, SOCKET_PORT, SOCKET_NAME)
textmsg("Connection to vision server has been opened.")
# Inside the main processing loop:
socket_send_string("ready\n", SOCKET_NAME)
data = socket_read_line(SOCKET_NAME, timeout=RESPONSE_TIMEOUT)
if data != "":
coords = data
comma1 = str_find(coords, ",") # position of the comma between X and Y
comma2 = str_find(coords, ",", comma1 + 1) # position of the comma between Y and Z
if (comma1 > -1) and (comma2 > -1):
x_vision = to_num(str_sub(coords, 0, comma1))
length_y = comma2 - (comma1 + 1)
y_vision = to_num(str_sub(coords, comma1 + 1, length_y))
length_z = str_len(coords) - (comma2 + 1)
z_vision = to_num(str_sub(coords, comma2 + 1, length_z))
# Close the connection once, when the program stops
socket_close(SOCKET_NAME)
x_vision, y_vision and z_vision are now numeric (float) and ready to use as position coordinates in a move command.
| Function | Type | Purpose |
|---|---|---|
str_find |
String | Returns the position of a character within a string |
str_sub |
String | Extracts part of a string, given a start position and length |
to_num |
Conversion | Converts a string to a numeric (float) value |
Troubleshooting / Common mistakes
- Opening/closing the socket inside the main loop instead of once at the start/end — causes reconnects, performance issues and can overload the network.
\nat the end of a sent string is the message delimiter thatsocket_read_linewaits for — forgetting it means the other side blocks until it times out.- If
socket_read_line/socket_read_ascii_floattimes out, it returns an empty string / a list starting with0— always check for this before parsing. - Two programs cannot bind to the same port at the same time on one machine.
socket_read_ascii_floatexpects the numbers formatted in parentheses and separated by commas, e.g.(1.2, 1.3, 1.4)— plain comma-separated text (no parentheses) will not parse correctly; usesocket_read_line+ manual parsing (step 9) for that instead.
Related
- How to find and set the IP address for connecting a PC to a UR robot — find/set the robot’s and your PC’s IP address
- How to find and set the IP address for connecting a PC to a UR robot — alternative: control the robot from Python with RTDE
- How to use a UP Board as a companion computer for a UR robot — using a UP board instead of a laptop as the PC side
- For the Doosan side of this connection, see How to connect a Doosan robot to a PC over a TCP socket (DRL Studio and Python) and How to connect a Doosan robot to a PC over a TCP socket (DRL Studio and Python).
Rewritten and consolidated (Sept 2026) from the original student how-to’s: Create TCP/IP connection between your PC and a Universal robot, How to send and receive information between python and UR5 robot, How to receive coordinates (x, y, z) with the universal robot via TCP/IP communication, How-to Connect a Cobot to your laptop using Python (Complete Guide), Connect a Universal robot to a Python program on a computer.