Python WebSockets: Build a Client and Server

Building a Python WebSocket example means connecting a client to a server. The websockets package lets them exchange messages over one connection that stays open until either side closes it.

This article shows how to install websockets and build a local echo client and server that handles more than one message.

TL;DR: Python WebSockets

The Python websockets package opens persistent connections so an asyncio client and server can exchange messages until either side closes the connection.

  • Install with python -m pip install websockets.
  • Use serve() for a server and connect() for a client.
  • Use async for to receive messages until disconnection.

What are WebSockets in Python?

A WebSocket is a protocol for two-way communication over one persistent connection. HTTP commonly follows a request and response, while a WebSocket lets either endpoint send another message without opening a new connection for each exchange.

I chose the standalone package for this example because it gives direct client and server APIs without a framework route. Its asyncio APIs use coroutines that pause while waiting for network activity. The documentation requires Python 3.11 or newer and lists no runtime dependencies.

How to build a Python WebSocket client and server

A single source file lets the server and client run together without leaving a listener behind.

Step 1: Install the websockets package

Install the package in the Python environment that will run the program. A virtual environment keeps dependencies separate. Our guide explains activating a virtual environment on Windows.

python -m pip install websockets

The command failed because pip is missing from this Python environment. Use an environment that includes pip, then run the install command there.

/home/ubuntu/.hermes/installs/5f0a1ff4045d044e/environments/c2be05dadc06453ab1086ce0dd328b57/venv/bin/python3: No module named pip
Terminal output from attempting to install the websockets package
The Python environment has no pip module, so installation did not run.

Check the package’s current Python requirement in its documentation before choosing an interpreter. Avoid copying the old tutorial handler signature that takes both a connection and a path. The current asyncio server handler receives the connection as its argument.

Step 2: Write a server handler

Use a server handler for each connection. Iterating asynchronously over that connection receives messages until a normal close, and sending a string returns a text message to that client.

async def echo(websocket):
    async for message in websocket:
        await websocket.send(f"Echo: {message}")

The asynchronous iterator is a good default for an echo server because it ends with the message stream instead of raising an exception for each ordinary disconnect. The official server reference documents the connection handler and server lifecycle.

Step 3: Start the server and connect a client

Set the handler and main function in a file named websocket_echo_demo.py.

import asyncio
from websockets.asyncio.client import connect
from websockets.asyncio.server import serve

async def echo(websocket):
    async for message in websocket:
        await websocket.send(f"Echo: {message}")

async def main():
    async with serve(echo, "127.0.0.1", 0) as server:
        port = server.sockets[0].getsockname()[1]
        async with connect(f"ws://127.0.0.1:{port}") as websocket:
            await websocket.send("Hello, server!")
            print(await websocket.recv())

if __name__ == "__main__":
    asyncio.run(main())

I ran the file with the command shown below. It printed the echo line.

python3 websocket_echo_demo.py
Echo: Hello, server!
Python WebSocket echo program output
The client receives the server’s echoed message.

Step 4: Handle more than one message

JSON distinguishes event types from payloads.

import json

async def handle_events(websocket):
    async for raw_message in websocket:
        event = json.loads(raw_message)
        if event.get("type") == "ping":
            await websocket.send(json.dumps({"type": "pong"}))

JSON is an application-level choice. Check decoded messages before acting on them.

What should you handle in a WebSocket connection?

The code uses port 0 because a fixed local port was already occupied during an earlier attempt.

A standalone client can use an async context manager to close the connection when the exchange ends. Use it unless the application needs to manage closure directly.

Blocking work stops the event loop from scheduling other connections. Use asynchronous waits or move CPU-heavy work outside the handler.

Secure connections and Origin checks matter for browser credentials. The server API accepts an origins option for checking the handshake header.

The connection list stays inside one process. Multiple server processes need shared routing, such as a message broker.

For asynchronous foundations, review these advanced Python concepts alongside the package examples.

Common errors with a Python WebSocket connection

A failed installation or handshake points to different layers. Check the interpreter, server address and connection lifecycle before changing application code.

SymptomCheckNext step
pip module missingWhich Python interpreter ran the install command?Use an environment with pip, then rerun the install command.
Connection refusedIs the server listening at the host and port in the WebSocket URI?Start the server and use its bound port.
Connection closes during receiveDid either endpoint close the connection or raise an error?Handle normal closure and report other connection errors.

The install attempt stopped before contacting a package index because pip was absent. The echo program ran in the environment that already had websockets.

Conclusion: Keep the connection lifecycle explicit

The core Python WebSockets approach uses a server handler that reads messages asynchronously and a client that manages its connection with a context manager. Build message format and authentication around that exchange.

For the current API and examples, read the websockets getting-started guide, the official server tutorial and Python’s asyncio documentation.

FAQ

These answers cover common setup and lifecycle questions.

How do I install websockets in Python?

Run python -m pip install websockets in the Python environment that will run your program. Current documentation requires Python 3.11 or newer.

How do I close a Python WebSocket connection?

Exit the async with connect(…) block to close the connection cleanly, or call close() when managing an awaited connection directly.

Why does my WebSocket server close after one message?

The handler may return after receiving one message. Iterate with async for message in websocket to process messages until the client disconnects.

Ashutosh Yadav
Ashutosh Yadav
Articles: 30