Registry / http-networking / wsproto

wsproto

JSON →
library1.3.2pypypi✓ verified 29d ago

wsproto is a pure-Python, sans-I/O implementation of the WebSocket protocol stack (RFC 6455) and its per-message compression extension (RFC 7692). It provides a low-level, state-machine-driven API, allowing developers to embed WebSocket communication into various programming paradigms without dictating network or concurrency models. The current version is 1.3.2, with releases occurring on an irregular but active basis as needed by the `python-hyper` community.

pip install wsproto
INSTALL
IMPORT
SIG · WSPROTO
W
wsproto
http-networkingpythonv1.3.2
Install
1.7s avg
Import
111ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v1.3.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.118s · 18.2MB
glibc
py 3.10–3.95 runs
installs and imports cleanly · install 1.7s · import 0.104s · 19MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

WSConnection
✓ from wsproto import WSConnection
✗ from wsproto.connection import WSConnection
Moved in version 0.13.0 for better discoverability and to be closer to other top-level classes. The old import path is now deprecated and removed in newer versions.
ConnectionType
✓ from wsproto import ConnectionType
✗ from wsproto.connection import ConnectionType
Similar to WSConnection, ConnectionType was moved to the top-level package for easier access.
Request
✓ from wsproto.events import Request
AcceptConnection
✓ from wsproto.events import AcceptConnection
Message
✓ from wsproto.events import Message
TextMessage
✓ from wsproto.events import TextMessage
CloseConnection
✓ from wsproto.events import CloseConnection

wsproto is a 'sans-I/O' library, meaning it handles the protocol state machine but not network communication. The quickstart demonstrates a simulated client-server interaction by manually passing bytes between two `WSConnection` instances. In a real application, `client_ws.send()`'s output would be written to a network socket, and `client_ws.receive_data()` would consume bytes read from that socket. Events are processed by iterating `ws.events()`.

from wsproto import WSConnection, ConnectionType from wsproto.events import Request, AcceptConnection, TextMessage, CloseConnection import socket import os # Example: Simple WebSocket client interaction (sans-I/O) # This code demonstrates the wsproto logic; actual network I/O is omitted for brevity. # In a real application, 'send_bytes_to_network' and 'receive_bytes_from_network' # would interact with a socket or other I/O primitive. def simulate_client_server_interaction(): client_ws = WSConnection(ConnectionType.CLIENT) server_ws = WSConnection(ConnectionType.SERVER) # Client initiates handshake client_handshake_request = client_ws.send(Request(host="example.com", target="/")) print(f"Client sends handshake request: {client_handshake_request!r}") # Server receives handshake request server_ws.receive_data(client_handshake_request) for event in server_ws.events(): if isinstance(event, Request): print(f"Server receives client Request: {event}") server_handshake_response = server_ws.send(AcceptConnection()) print(f"Server sends handshake response: {server_handshake_response!r}") break # Client receives handshake response client_ws.receive_data(server_handshake_response) for event in client_ws.events(): if isinstance(event, AcceptConnection): print(f"Client receives Server Acceptance: {event}") break # Client sends a message client_message_bytes = client_ws.send(TextMessage(data="Hello from client!")) print(f"Client sends message: {client_message_bytes!r}") # Server receives the message server_ws.receive_data(client_message_bytes) for event in server_ws.events(): if isinstance(event, TextMessage): print(f"Server receives message: {event.data!r}") if event.message_finished: # Server echoes back server_response_bytes = server_ws.send(TextMessage(data=f"Echo: {event.data.decode()}")) print(f"Server sends echo: {server_response_bytes!r}") break # Client receives server's echo client_ws.receive_data(server_response_bytes) for event in client_ws.events(): if isinstance(event, TextMessage): print(f"Client receives echo: {event.data.decode()!r}") break # Client initiates close client_close_bytes = client_ws.send(CloseConnection(code=1000, reason="Done")) print(f"Client sends close frame: {client_close_bytes!r}") # Server receives close server_ws.receive_data(client_close_bytes) for event in server_ws.events(): if isinstance(event, CloseConnection): print(f"Server receives CloseConnection: {event}") server_close_response = server_ws.send(event.response()) print(f"Server sends close response: {server_close_response!r}") break # Client receives server's close response client_ws.receive_data(server_close_response) for event in client_ws.events(): if isinstance(event, CloseConnection): print(f"Client receives CloseConnection response: {event}") break simulate_client_server_interaction()
Debug
Known issues
gotchawsproto is a 'sans-I/O' library. It manages the WebSocket protocol state but does not perform any network I/O itself. Users must implement their own 'network glue' to send and receive bytes over the actual network (e.g., using `socket` or an async I/O library) and feed them into `wsproto`.
fix
Be prepared to manage your own network sockets and I/O loops. `wsproto.WSConnection.send()` returns bytes to transmit, and `wsproto.WSConnection.receive_data(data)` takes bytes received from the network.
affects: All versions
gotchaWhen the underlying network connection drops unexpectedly (e.g., `socket.recv()` returns zero bytes), you must call `ws.receive_data(None)` to inform `wsproto` of the connection closure and update its internal state. Failing to do so can leave the connection in an inconsistent state.
fix
Upon detecting a connection drop (e.g., `recv()` returning `b''`), call `ws.receive_data(None)` immediately before tearing down the connection.
affects: All versions
gotchaFor correct protocol behavior, both client and server connections *must* respond to certain control frames. Specifically, a received `Ping` event requires sending a `Pong` event (use `event.response()`), and a received `CloseConnection` event requires sending a `CloseConnection` event back (also `event.response()`).
fix
Always iterate `ws.events()` after receiving data and ensure you handle `Ping` and `CloseConnection` events by sending their respective responses using `ws.send(event.response())`.
affects: All versions
gotchaWebSocket data messages (TextMessage, BinaryMessage) can be fragmented across multiple `Message` events. The `data` field of these events represents only a chunk of the message. Applications need to buffer and reassemble these chunks until `event.message_finished` is `True` to get the complete logical message.
fix
Maintain a buffer for incoming message data and append `event.data` until `event.message_finished` indicates the full message has arrived. Then, process the complete buffered message.
affects: All versions
breakingThe primary `WSConnection` class was moved from `wsproto.connection.WSConnection` to `wsproto.WSConnection` in version 0.13.0. Additionally, the method to feed data into the connection was renamed from `receive_bytes` to `receive_data` in the same version.
fix
Update imports from `from wsproto.connection import WSConnection` to `from wsproto import WSConnection`. Replace calls to `ws.receive_bytes(data)` with `ws.receive_data(data)`.
affects: Prior to 0.13.0 to 0.13.0+
gotchaWhen processing `wsproto` events, `event.data` for `TextMessage` events is a Unicode string (`str`), while for `BinaryMessage` events it is bytes (`bytes`). Attempting to call `.decode()` on `event.data` from a `TextMessage` will result in an `AttributeError` because strings do not have a `.decode()` method.
fix
Check the type of the event (e.g., `isinstance(event, wsproto.events.TextMessage)`) before processing its data. If `event` is a `TextMessage`, `event.data` is already a string and should be used directly. If `event` is a `BinaryMessage`, `event.data` is bytes and can be decoded if a string representation is needed.
affects: All versions
gotchaWhen processing `Message` events (like `TextMessage` or `BinaryMessage`), be aware of the type of `event.data`. For `TextMessage` events, `event.data` is a `str`. For `BinaryMessage` events, `event.data` is `bytes`. Attempting to `decode()` a `str` or `encode()` bytes unnecessarily will result in an `AttributeError` or `TypeError`.
fix
For `TextMessage` events, `event.data` is already a string; use it directly or `encode()` it to bytes if the target API expects bytes. For `BinaryMessage` events, `event.data` is bytes; use it directly or `decode()` it to a string if the target API expects a string (specifying encoding).
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'wsproto'
The 'wsproto' library is not installed in your current Python environment.
fix
pip install wsproto
AttributeError: 'Connection' object has no attribute 'send_message'
Developers often expect a high-level 'send_message' method, but 'wsproto' provides a low-level 'send' method for sending individual WebSocket frames.
fix
Use the `connection.send()` method with raw bytes and an appropriate WebSocket opcode (e.g., `Opcode.TEXT`, `Opcode.BINARY`).
wsproto.utilities.InvalidStateError
An operation was attempted on the `wsproto.Connection` object when it was not in the correct state to perform that action (e.g., calling `accept()` on an already accepted connection).
fix
Implement proper state handling by checking `connection.state` before attempting operations, ensuring they align with the connection's current lifecycle stage.
wsproto.utilities.ProtocolError
The `wsproto` connection received bytes that do not conform to the WebSocket protocol specification (e.g., malformed frame header, invalid opcode, or reserved bits set incorrectly).
fix
Verify that the data being sent to `connection.receive_data()` is valid WebSocket protocol data, debugging the sender or network for corruption or non-compliance.
Upgrade
Version history
1.3.2latest on PyPI · released Nov 20, 2025
Audit
Dependencies
h11optionalOften used for HTTP/1.1 handshake by projects integrating wsproto, though not a direct dependency of wsproto itself.
hyper-h2optionalRecommended for HTTP/2 WebSocket support, requires external HTTP/2 parser.
Agent activity
43 hits · last 30 days
node
34
OpenAI (training)
1
Resources