Getting Started with Sanic WebSockets
Sanic has gained momentum as a high-performance Python web framework designed with speed and developer experience in mind.
The framework offers a clean, intuitive interface for implementing real-time communication, enabling you to craft responsive applications with features like instant messaging, live notifications, and dynamic content updates.
This practical guide will take you through building WebSocket functionality in Sanic step by step, using patterns that remain effective as your application grows.
Prerequisites
Before exploring Sanic WebSocket development, confirm you have Python 3.8 or newer on your system. Familiarity with Python's async/await syntax will prove beneficial since Sanic embraces asynchronous programming throughout its design.
Understanding JavaScript fundamentals will also help when we create interactive web interfaces to demonstrate our WebSocket functionality.
Establishing your Sanic WebSocket environment
Creating reliable real-time applications begins with effective project organization that clearly separates different concerns. We'll establish a solid foundation to keep WebSocket management well-organized, leveraging Sanic's simple async architecture.
Begin by establishing your development environment with dependency isolation:
These steps create your project workspace, establish an isolated Python environment, and activate it to maintain clean dependency management separate from other projects.
Install Sanic with its comprehensive feature set:
Sanic distinguishes itself by including WebSocket support directly in the core framework. This integrated approach eliminates the need for additional packages while providing robust real-time communication capabilities without extra configuration overhead.
Establish your application structure with the foundational file:
This initial setup provides the core structure for WebSocket development. Sanic's unified handling of both HTTP and WebSocket protocols simplifies development, while debug mode offers valuable development features, including automatic code reloading and comprehensive error reporting.
Sanic treats WebSocket connections with the same importance as HTTP routes, providing a consistent development experience. WebSocket handlers accept two arguments: the HTTP request context and the WebSocket connection instance, giving you access to both request information and bidirectional communication capabilities.
Create a foundational echo server that illustrates essential WebSocket patterns:
The async for construct automatically manages the message reception cycle, creating more maintainable and readable code. This pattern eliminates manual while True loops while delivering identical message-processing functionality.
The iteration concludes automatically when connections close, streamlining connection lifecycle management significantly.
Developing a comprehensive client interface with templates
Professional real-time applications benefit from proper separation of concerns, keeping HTML templates, CSS styles, and JavaScript logic in dedicated files.
Let's restructure your WebSocket interface using Sanic's templating capabilities with organized static assets.
First, install the required dependencies:
Create the proper directory structure for your templates and static assets:
Create your main template file with dynamic content placeholders and clean HTML structure:
This HTML template uses Jinja2 variables like {{ title }} and {{ subtitle }} for dynamic content that can be customized from your Python code. The template links to external CSS and JavaScript files using /static/ paths, which Sanic will serve automatically. The structure includes a statusIndicator for connection status, messageArea for displaying chat messages, and an input section with a text field and send button. Notice how the input field starts disabled - this prevents users from sending messages before the WebSocket connection is established.
Create your stylesheet with modern design, animations, and responsive layout:
This stylesheet creates a modern chat interface with professional styling and user experience enhancements.
The .status-bar classes use different background colors to indicate connection states - yellow for connecting, green for connected, and red for disconnected.
The @keyframes messageSlide animation makes new messages appear smoothly, sliding up from below with a fade-in effect. Notice how .message.outbound uses align-self: flex-end to position sent messages on the right, while .message.inbound aligns received messages to the left.
Create your JavaScript WebSocket client with advanced features like reconnection and error handling:
This JavaScript class provides a production-ready WebSocket client with sophisticated features. The constructor initializes reconnection parameters like maxReconnectAttempts = 3 and reconnectDelay = 1000, ensuring the client automatically tries to reconnect if the connection drops.
The establishConnection() method intelligently detects whether to use ws:// or wss:// protocols based on the current page protocol. In setupWebSocketHandlers(), the onmessage event handler uses a try-catch block to first attempt parsing messages as JSON, then falls back to plain text - this allows the same client to handle both simple echo messages and structured data from broadcasting features.
The attemptReconnection() method implements exponential backoff by multiplying the delay by the attempt number, preventing the client from overwhelming a recovering server. The transmitMessage() method includes validation to ensure messages aren't sent when the connection isn't ready, using this.socket?.readyState !== WebSocket.OPEN for safe checking.
Now update your main application file to use templates and serve static files:
This enhanced application integrates several important components for professional WebSocket development.
The SanicJinja2 import and setup enables template rendering, while FileSystemLoader('templates') tells Jinja2 where to find template files.
The app.static('/static', './static') line creates a route that serves all files from the static directory - when browsers request /static/css/style.css, Sanic automatically serves the file from ./static/css/style.css.
The jinja.render() method in the index route passes template variables as keyword arguments, making the interface customizable without hardcoding text.
The WebSocket handler now includes comprehensive logging with logger.info() calls to track connection lifecycle and message flow. The specific handling of asyncio.CancelledError is crucial - this exception occurs when clients disconnect unexpectedly (like closing a browser tab), and treating it separately from other exceptions prevents false error reports in your logs.
Testing your WebSocket implementation
Launch your Sanic application and verify the real-time communication:
The server will display startup information confirming successful initialization:
Open your browser to http://localhost:8000. The connection status will transition from "Establishing connection..." to "Connected to Sanic server" as the WebSocket connection initializes successfully:
The interface displays a welcome message immediately upon connection, confirming your WebSocket handler functions correctly. Notice how the status bar changes from yellow "Establishing connection..." to green "Connected to Sanic server", indicating a successful WebSocket handshake. The input field becomes enabled and focuses automatically, ready for user interaction.
Enter messages in the input field and press Enter to observe instant echo responses, demonstrating bidirectional communication capabilities:
Type any message like "test message" and press Enter. The message appears immediately on the right side as an outbound message (styled with the gradient background), while the server's echo response appears on the left as an inbound message:
This demonstrates the complete WebSocket communication cycle - your message travels from the client to the server through the WebSocket connection, gets processed by the websocket_handler() function, and returns as an echo response.
Final thoughts
This guide took you through building WebSocket functionality in Sanic, starting with basic echo servers and advancing to professional applications with modern templates, styling, and error handling.
Sanic's built-in WebSocket support makes real-time development straightforward by eliminating the complexity found in other frameworks. You can focus on your application logic while Sanic handles the infrastructure. The async/await patterns work naturally with modern Python development, and the framework's performance makes it excellent for high-traffic real-time applications.
As your applications grow, you can extend this foundation with user authentication, message persistence using databases like PostgreSQL or Redis, and horizontal scaling with message brokers. The Sanic documentation provides detailed guidance on security, performance optimization, and deployment best practices.