WebSocket Chat Room
Real-time chat — messages broadcast to every connected browser instantly. FastAPI WS + vanilla JS client.
🚀 Mini Project · 3 filesProject files
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
import uvicorn
app = FastAPI()
# Track all connected clients
clients: set[WebSocket] = set()
@app.get('/')
async def get():
return HTMLResponse(open('index.html').read())
@app.websocket('/ws')
async def ws_endpoint(ws: WebSocket):
await ws.accept()
clients.add(ws)
try:
while True:
msg = await ws.receive_text()
# Broadcast to every connected client
for c in list(clients):
await c.send_text(msg)
except WebSocketDisconnect:
clients.remove(ws)
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
<!DOCTYPE html>
<html>
<head><title>Chat</title>
<style>
#msgs { height: 300px; overflow-y: scroll; border: 1px solid #ccc;
padding: 0.5rem; margin-bottom: 0.5rem; }
.msg { margin: 0.25rem 0; }
input { padding: 0.5rem; }
</style></head>
<body>
<div id='msgs'></div>
<input id='input' placeholder='type a message' size='50'>
<script>
const ws = new WebSocket('ws://' + location.host + '/ws');
const msgs = document.getElementById('msgs');
const input = document.getElementById('input');
ws.onmessage = (e) => {
const div = document.createElement('div');
div.className = 'msg';
div.textContent = e.data;
msgs.appendChild(div);
msgs.scrollTop = msgs.scrollHeight; // auto-scroll
};
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && input.value.trim()) {
ws.send(input.value);
input.value = '';
}
});
ws.onclose = () => {
setTimeout(() => location.reload(), 2000); // reconnect
};
</script>
</body>
</html>
pip install fastapi uvicorn python main.py # Open http://localhost:8000 in TWO browser tabs # Type a message in either tab — it appears in both instantly
How it works
WebSockets give you a persistent bidirectional connection — either side can send at any time, unlike HTTP where the client must ask. The chat flow: (1) Browser opens ws://localhost:8000/ws. The server accepts and adds the WebSocket to a set of connected clients. (2) User types a message and hits Enter. ws.send(input.value) sends it to the server. (3) The server receives it via ws.receive_text(), then loops over every connected client and sends the same message. This is the 'broadcast' pattern — one message goes to everyone. (4) Each browser's ws.onmessage fires, appends the message to the DOM, and auto-scrolls to the bottom. (5) On disconnect (user closes tab), the WebSocketDisconnect exception fires, the server removes the client from the set. (6) ws.onclose on the client triggers a reload after 2s — basic auto-reconnect. Open two browser tabs to see real-time sync.
⚡ Open in Notebook