The direct answer to how to access Raspberry Pi from PC without a monitor or keyboard is to perform a headless setup: enable SSH via the Raspberry Pi Imager before flashing the OS, connect both devices to the same local subnet, and use an SSH client (like Windows Terminal or PuTTY) to connect to the Pi's local IP address on port 22. Once connected, you can deploy Python scripts to control hardware remotely.
In this guide, we are targeting the Raspberry Pi 5 (8GB variant) running the current 64-bit Raspberry Pi OS. We will walk through the exact network port mappings, wire a 5V relay for remote hardware control, deploy a robust Python TCP server for GPIO toggling, and debug the exact error strings that halt most headless builds.
Hardware Spec Sheet & Network Port Mapping
Before writing code, you need to know which ports to open on your PC's firewall and which protocols offer the best latency for embedded control. The table below outlines the standard access methods when bridging a PC to a headless Pi.
| Access Method | Port | Protocol | Avg Latency (LAN) | Payload Overhead | Primary Use Case |
|---|---|---|---|---|---|
| SSH (Secure Shell) | 22 | TCP | < 2ms | High (Encryption) | Terminal access, file transfer (SCP/SFTP), script deployment |
| VNC (Virtual Network) | 5900 | TCP | 15-40ms | Very High (Video) | Remote GUI desktop access (requires wayvnc on Bookworm/Trixie) |
| Custom TCP Socket | 8000-9999 | TCP | < 1ms | Minimal (Raw bytes) | Direct PC-to-Pi GPIO relay triggering via Python scripts |
| MQTT (Mosquitto) | 1883 | TCP | 2-5ms | Low (Header + Topic) | IoT sensor telemetry, asynchronous state publishing |
Wiring the Remote Relay: Pi 5 Pinout
For this build, we are controlling a 5V 1-channel relay module. A common mistake hobbyists make is powering the relay coil directly from the Pi's 3.3V logic pins, which causes brownouts and crashes the Pi 5's PMIC. We will use the 5V rail for the coil and an optocoupler-isolated input to protect the 3.3V BCM logic.
Parts List:
- Raspberry Pi 5 (8GB RAM) with Active Cooler
- Official 27W USB-C PD Power Supply (Critical for Pi 5 peripheral headroom)
- 5V 1-Channel Relay Module (Optocoupler isolated, SRD-05VDC-SL-C)
- 22 AWG solid core jumper wires
Pin Mapping Table
| Pi 5 Physical Pin | BCM GPIO | Function | Relay Module Terminal | Wire Color (Recommended) |
|---|---|---|---|---|
| Pin 2 | N/A (5V Power) | VCC (Coil Power) | VCC | Red |
| Pin 6 | N/A (Ground) | GND (Common) | GND | Black |
| Pin 11 | GPIO 17 | Logic Trigger | IN (Signal) | Yellow |
Always verify your relay module's trigger logic. Most optocoupler modules are active-low, meaning the relay engages when the GPIO pin is pulled to GND (0V). The Python code below accounts for this by setting active_high=False.
Compilable Python Code for Remote GPIO Control
This script creates a lightweight TCP socket server on the Pi. Your PC can send simple string commands (ON, OFF, STATUS) over the network to toggle the physical relay. It uses the gpiozero library, which is pre-installed on modern Raspberry Pi OS and handles the underlying lgpio hardware abstraction safely.
import socket
import signal
import sys
from gpiozero import OutputDevice
# --- PIN DEFINITIONS & CONFIG ---
RELAY_PIN = 17 # BCM GPIO 17 (Physical Pin 11)
HOST = '0.0.0.0' # Listen on all local interfaces
PORT = 9999 # Custom TCP port for remote access
BUFFER_SIZE = 1024
# Initialize relay (active_high=False for standard optocoupler modules)
relay = OutputDevice(RELAY_PIN, active_high=False, initial_value=False)
def graceful_shutdown(signum, frame):
"""Safely turn off relay and close socket on Ctrl+C or SIGTERM."""
print('\n[SYSTEM] Shutting down server and resetting GPIO...')
relay.off()
relay.close()
sys.exit(0)
# Register signal handlers for clean exit
signal.signal(signal.SIGINT, graceful_shutdown)
signal.signal(signal.SIGTERM, graceful_shutdown)
def start_server():
try:
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Allow port reuse to prevent Errno 98 on quick restarts
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((HOST, PORT))
server_socket.listen(5)
print(f'[SERVER] Listening on {HOST}:{PORT} | Relay PIN: BCM {RELAY_PIN}')
while True:
client_socket, addr = server_socket.accept()
print(f'[CONN] Accepted connection from {addr[0]}:{addr[1]}')
try:
data = client_socket.recv(BUFFER_SIZE).decode('utf-8').strip().upper()
response = 'ERR: Unknown command'
if data == 'ON':
relay.on()
response = 'ACK: Relay ON'
elif data == 'OFF':
relay.off()
response = 'ACK: Relay OFF'
elif data == 'STATUS':
state = 'ON' if relay.value else 'OFF'
response = f'STATE: {state}'
client_socket.sendall(response.encode('utf-8'))
except ConnectionResetError:
print(f'[WARN] Client {addr[0]} disconnected abruptly.')
finally:
client_socket.close()
except OSError as e:
print(f'[FATAL] Socket error: {e}')
sys.exit(1)
if __name__ == '__main__':
start_server()
How to run it: Save the file as relay_server.py on the Pi via SSH. Execute it using python3 relay_server.py. To test from your PC, open a terminal and use netcat: echo "ON" | nc [PI_IP_ADDRESS] 9999.
Debugging Connection & GPIO Errors
When learning how to access Raspberry Pi from PC, you will inevitably hit network or permission walls. Here are the exact error strings and their ranked causes.
Error 1: ssh: connect to host 192.168.x.x port 22: Connection timed out
This means your PC cannot route traffic to the Pi's IP at the TCP layer.
- SSH is not enabled: Raspberry Pi OS disables SSH by default for security. You must place an empty file named
ssh(no extension) in the/boot/firmware/partition of the SD card before booting, or enable it via the Imager's OS customization settings. - AP Isolation / Guest Network: If your PC and Pi are on a router's "Guest" WiFi, client-to-client communication is blocked at the access point level. Move both to the main LAN.
- DHCP Lease Failure: The Pi didn't get an IP. Connect a monitor temporarily and run
ip a, or check your router's DHCP client table for a device namedraspberrypi.
Error 2: OSError: [Errno 98] Address already in use
This occurs when starting the Python TCP server.
- Zombie Process: A previous instance of the script crashed but left the socket bound. Run
sudo lsof -i :9999to find the PID, thenkill -9 [PID]. - TIME_WAIT State: The OS is holding the port open after a recent closure. The
SO_REUSEADDRflag in the provided code prevents this, but if you omitted it, wait 60 seconds or reboot the Pi.
Error 3: gpiozero.exc.PinFactoryFallback: Falling back from rpigpio
- Missing Backend: The Pi is trying to use the legacy
RPi.GPIOlibrary, which is largely deprecated on Pi 5 / Bookworm OS. Ensurelgpiois installed (sudo apt install python3-lgpio) sogpiozerocan use the modern hardware interface. - Permission Denied: Your user is not in the
gpiogroup. Fix withsudo usermod -aG gpio $USERand log out/back in.
1. Verify the
ssh file exists in the boot partition.2. Confirm subnet matching (e.g., PC is
192.168.1.10 and Pi is 192.168.1.50, both with a 255.255.255.0 mask).3. Check for power brownout throttling, which disables peripherals and drops WiFi. SSH in and run
dmesg | grep -i voltage. If you see "Under-voltage detected", upgrade to the official 27W PD supply.
Extending or Simplifying Your Remote Build
Depending on your project's end goal, you can scale this architecture up or down.
How to Simplify (Zero-Config GUI Access):
If you don't actually need raw GPIO control and just want to see the Pi's desktop from your PC, skip the SSH terminal entirely. Use Raspberry Pi Connect (currently in beta/rollout via Raspberry Pi's official services). It creates a secure WireGuard tunnel out of the box, allowing browser-based remote desktop access without touching your router's port forwarding or dealing with local IP changes.
How to Extend (IoT & Cloud Integration):
Raw TCP sockets are great for local LAN control, but they lack encryption and state retention. To extend this build for a smart home or remote greenhouse:
- Replace the
socketlibrary withpaho-mqtt. - Install Mosquitto on the Pi (
sudo apt install mosquitto mosquitto-clients). - Publish state changes to a topic like
home/greenhouse/relay1. - This allows your PC, phone, and home automation hub (like Home Assistant) to subscribe to the relay's state simultaneously, providing true multi-client embedded control.
By mastering headless SSH and direct socket-to-GPIO mapping, you eliminate the need for a dedicated monitor stack on your workbench, turning the Raspberry Pi 5 into a true headless embedded controller.






