Build Real-Time Communication with Python and WebSockets
Modern applications are expected to respond instantly. Whether it is a chat application, live notification system, multiplayer game, collaborative editor, or monitoring dashboard, users increasingly expect information to appear without repeatedly refreshing a webpage.
One technology that makes this possible is WebSockets.
Combined with Python, WebSockets provide a straightforward way to create applications where the client and server can communicate continuously. Instead of opening a new HTTP connection for every request, a WebSocket connection stays open and allows both sides to exchange messages whenever needed.
This article explains how to build a simple real-time communication system with Python and WebSockets, how it works, and how you can extend it into a more practical application.
What Are WebSockets?
Traditional HTTP communication usually follows a request-response pattern.
The browser sends a request:
Client → Server
The server processes it and sends a response:
Server → Client
The connection is generally finished after the response.
This approach works extremely well for websites and APIs, but it becomes inefficient when information needs to be delivered continuously.
Imagine a chat application. If someone sends you a message, the browser needs to discover that message somehow. One approach is polling—asking the server every few seconds whether anything has changed.
WebSockets solve this differently.
Once a WebSocket connection has been established, it can remain open:
Client ↔ Server
Either side can send information when necessary.
That makes WebSockets particularly useful for real-time communication.
Why Use Python?
Python has a large ecosystem for building web applications and network services. Developers can choose from several frameworks and libraries depending on their requirements.
For a simple demonstration, FastAPI combined with its WebSocket support provides a clean approach.
You can install the required packages with:
pip install fastapi uvicorn
FastAPI provides the application framework, while Uvicorn can run the application as an ASGI server.
Creating a WebSocket Server
Let's start with a minimal server.
Create a file called main.py:
from fastapi import FastAPI, WebSocket
app = FastAPI()
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
message = await websocket.receive_text()
await websocket.send_text(f"Server received: {message}")
This small program does several things.
First, it creates a FastAPI application.
The /ws endpoint is configured as a WebSocket endpoint rather than a normal HTTP route.
When a client connects, the server accepts the WebSocket connection:
await websocket.accept()
The server then waits for messages:
message = await websocket.receive_text()
After receiving one, it sends a response:
await websocket.send_text(...)
The while loop keeps the communication alive.
Running the Server
Start the application with:
uvicorn main:app --reload
The server will normally become available locally through port 8000.
Your WebSocket endpoint will be:
ws://localhost:8000/ws
Notice that WebSockets use ws:// rather than the familiar http://.
For encrypted connections, you would use wss://.
Connecting from a Browser
You can create a simple HTML page to communicate with the Python server.
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Demo</title>
</head>
<body>
<input id="message" placeholder="Enter message">
<button onclick="sendMessage()">Send</button>
<div id="output"></div>
<script>
const socket = new WebSocket("ws://localhost:8000/ws");
socket.onopen = () => {
console.log("Connected to server");
};
socket.onmessage = (event) => {
document.getElementById("output").innerHTML +=
`<p>${event.data}</p>`;
};
function sendMessage() {
const input = document.getElementById("message");
socket.send(input.value);
input.value = "";
}
</script>
</body>
</html>
When the page connects, the browser establishes a WebSocket connection with the Python server.
When you click Send, the browser transmits the message.
The Python server receives it and sends a response back.
The browser receives that response through:
socket.onmessage
No page refresh is required.
Turning It Into a Chat Server
A more useful example is a basic chat room.
The server needs to keep track of connected clients.
One simple implementation looks like this:
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
app = FastAPI()
connections = []
@app.websocket("/chat")
async def chat(websocket: WebSocket):
await websocket.accept()
connections.append(websocket)
try:
while True:
message = await websocket.receive_text()
for connection in connections:
await connection.send_text(message)
except WebSocketDisconnect:
connections.remove(websocket)
Now, whenever one client sends a message, the server broadcasts it to the connected clients.
This is the basic architecture behind many real-time applications.
However, this example is intentionally simple. A production system needs additional handling for authentication, connection failures, multiple server instances, message persistence, and security.
Adding Usernames
Instead of sending plain messages, you can send structured data.
JSON is a common choice.
For example:
{
"username": "Alex",
"message": "Hello everyone!"
}
Python can receive JSON using:
data = await websocket.receive_json()
You can then broadcast information such as:
await connection.send_json({
"username": data["username"],
"message": data["message"]
})
This makes it easier for the frontend to display usernames, timestamps, message types, and other metadata.
Handling Disconnections
Real-time applications must assume that users can disappear unexpectedly.
A phone may lose its internet connection. A browser tab may close. A laptop may enter sleep mode.
FastAPI provides WebSocketDisconnect for handling this situation.
try:
while True:
message = await websocket.receive_text()
except WebSocketDisconnect:
print("Client disconnected")
Proper cleanup prevents disconnected connections from remaining in your server's connection list.
WebSockets Beyond Chat
Chat is only one application.
The same technology can power many other systems.
Live Notifications
An application can immediately notify users when something happens.
For example:
- New order received
- Payment completed
- New comment posted
- Task assigned
- Server alert triggered
Real-Time Dashboards
A monitoring application can continuously send updated information to a browser.
Instead of refreshing the dashboard every few seconds, the server pushes new values as they become available.
Multiplayer Games
Game clients can exchange state information with a server in near real time.
Latency becomes particularly important here, so application architecture and network efficiency need careful attention.
Collaborative Applications
Documents, whiteboards, and project-management tools can use WebSockets to synchronize changes between users.
When one person modifies an object, other connected users can receive the update almost immediately.
WebSockets vs HTTP
WebSockets and HTTP are not competing technologies in every situation. They solve different problems.
| Feature | HTTP | WebSockets |
|---|---|---|
| Communication | Request/response | Two-way |
| Persistent connection | Usually no | Yes |
| Server can push data | Limited | Yes |
| Real-time applications | Less suitable | Excellent |
| Typical usage | Websites and APIs | Chat, live updates, games |
A modern application can use both.
For example, HTTP might handle login, user profiles, and normal API requests, while WebSockets handle live messages and notifications.
Important Security Considerations
Real-time communication should not be treated as automatically secure.
For production applications, consider using:
wss://instead of unencryptedws://- Authentication
- Authorization
- Input validation
- Rate limiting
- Connection limits
- Message-size limits
- Proper error handling
- Origin validation
Never assume that a connected WebSocket client is trustworthy.
If users can send arbitrary content to other users, validate and sanitize that data appropriately.
Scaling a WebSocket Application
The simple examples above work well for learning, but scaling introduces new challenges.
Imagine running three Python servers.
A user connected to Server A sends a message. Another user connected to Server C needs to receive it.
The message cannot simply remain inside Server A's memory.
This is where technologies such as Redis or dedicated messaging systems can become useful. Servers can share events through a central message broker or other distributed infrastructure.
For large applications, you may also need:
- Load balancing
- Connection management
- Horizontal scaling
- Message queues
- Persistent storage
- Monitoring
- Automatic reconnection
The architecture becomes more complex as the number of concurrent connections grows.
Final Thoughts
Python and WebSockets provide an accessible way to begin building real-time applications.
The fundamental idea is simple: establish a persistent connection and allow the client and server to exchange messages whenever necessary.
With FastAPI, creating a basic WebSocket endpoint requires surprisingly little code. From there, you can build chat rooms, live dashboards, notification systems, collaborative applications, and other interactive services.
The real challenge comes when moving from a small demonstration to production. Authentication, security, reconnection, scaling, and reliable message delivery all become important.
Still, WebSockets remain one of the most useful technologies to learn if you want to build modern applications where information moves instantly instead of waiting for the next page refresh.