Library / SDK
python-websockets/websockets avatar
python-websockets/websockets

websockets: a Python WebSocket library for asyncio, threading and trio

Library for building WebSocket servers and clients in Python

5,721 stars617 forksPythonBSD-3-Clause

At a glance

What is it?
The python-websockets/websockets package implements RFC 6455 and RFC 7692 for Python 3.11 and later, with coroutine, thread and trio APIs plus a Sans-I/O layer. It is a protocol library, not an HTTP framework, and that boundary decides who should install it.
Who is it for?
Adopt websockets when you need a correct RFC 6455 implementation in Python and your application logic is already asynchronous or can be made so. Do not adopt it if you need callbacks instead of coroutines, or if you want one server that serves both a full HTTP application and WebSocket upgrades: the README states its HTTP support is minimal, just enough for a health check, and points at uvicorn or Sanic for that combination.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What websockets solves, and the developers it targets

A WebSocket connection is not a socket you can read from and write to whenever you like. It begins as an HTTP request that gets upgraded, then frames every message with a length, an opcode and a mask, and expects pings, pongs and close handshakes at defined moments. Getting that state machine right for one client is tedious. Getting it right under load, with partial frames and a peer that stops reading, is where hand-rolled implementations fail.

websockets exists to own that state machine. The README describes it as a library for building WebSocket servers and clients in Python with a focus on correctness, simplicity, robustness and performance, and states that it is heavily tested for compliance with RFC 6455, with continuous integration failing under 100 percent branch coverage. The intended reader is a Python developer who already has an application protocol in mind and wants the transport handled. The pyproject.toml sets requires-python to >=3.11, so the audience is narrowed further: this is not a library for projects still on older interpreters.

Three APIs and a Sans-I/O layer: how the code is arranged

The package does not ship one interface. It ships several implementations of the same protocol, and the import path tells you which one you are getting. The default is built on asyncio, Python's standard asynchronous I/O framework, and the README calls its API coroutine-based. A second implementation sits on top of threading and is reached through websockets.sync. A third targets trio. Below all of them, the README mentions a Sans-I/O layer for integration in third-party projects, which is the piece other servers consume when they want websockets to handle framing while they keep control of the event loop and the socket.

The data flow in the asyncio server is deliberately small. You write an async function that receives a connection object. Iterating over that object yields incoming messages; calling send on it emits outgoing ones. Everything else, the opening handshake, frame parsing, fragmentation reassembly, ping and pong handling, compression negotiation and the closing handshake, happens inside the library. The README reduces the mental model to msg = await ws.recv() and await ws.send(msg).

The performance story is partly a compiled extension. setup.py builds a websockets.speedups extension from src/websockets/speedups.c, and the build is optional unless the BUILD_EXTENSION environment variable is set to yes or no. The pyproject.toml cibuildwheel configuration lists many Linux architectures including aarch64, ppc64le, riscv64 and s390x, plus macOS arm64, x86_64 and universal2, and Windows AMD64, ARM64 and x86. Where a matching wheel exists, the extension arrives pre-compiled; where it does not, the pure-Python path still runs.

Installing websockets and running a first echo server

The package is distributed on PyPI under the name websockets. Install it into the environment you intend to run, and note that the project requires Python 3.11 or later.

bash
pip install websockets

If you want to confirm the version that landed, the project also registers a console script named websockets through the [project.scripts] table in pyproject.toml, pointing at websockets.cli:main. The README does not document its subcommands, so treat it as a discovery step rather than a documented workflow.

The smallest useful program is the echo server from the README. Save it as echo.py and run it with python echo.py.

python
import asyncio
from websockets.asyncio.server import serve

async def echo(websocket):
    async for message in websocket:
        await websocket.send(message)

async def main():
    server = await serve(echo, "localhost", 8765)
    await server.serve_forever()

asyncio.run(main())

The serve call binds to localhost on port 8765 and returns a server object; serve_forever keeps the process alive. Each accepted connection runs the echo coroutine. The async for loop ends when the client disconnects or the connection closes, and the coroutine returns.

To exercise it, the README gives a client using the threading API. In a second terminal, run this and you should see the printed line Received: Hello world!.

python
from websockets.sync.client import connect

def hello():
    with connect("ws://localhost:8765") as websocket:
        websocket.send("Hello world!")
        message = websocket.recv()
        print(f"Received: {message}")

hello()

The two snippets deliberately use different APIs. That is a fair illustration of the library's range, but it also means the sync client and the asyncio server are separate code paths with separate behaviors to learn.

Where websockets is the wrong choice

The README answers this directly, which is unusual and useful. If you prefer callbacks over coroutines, it says to pick another library, because websockets was created to provide the best coroutine-based API for managing WebSocket connections in Python. That is a design commitment, not a missing feature, and it will not be reversed for your use case.

The second limitation is HTTP. The library aims at being an excellent implementation of RFC 6455 and RFC 7692, the compression extension. Its HTTP support is minimal, described as just enough for an HTTP health check. If your service must serve a REST API, static files and a WebSocket endpoint on one port, websockets alone will not do it. The README points to uvicorn and Sanic as servers that build on top of websockets to support WebSocket connections, which is the honest routing of that requirement elsewhere.

There is a third constraint that the README does not spell out but the repository layout implies. The Makefile exports PYTHONASYNCIODEBUG, sets PYTHONPATH to src and runs the suite with python -m unittest, and the coverage target fails under 100 percent. That is a project optimized for a very high correctness bar, and it also means the supported surface is narrow by design. Features outside the protocol, such as authentication, session management or message routing, are yours to build.

How websockets differs from a full ASGI server such as uvicorn

The realistic alternative for most readers is not another WebSocket-only library but an ASGI server that speaks WebSocket as one of several protocols. uvicorn is the example the README itself names. The difference is architectural rather than a matter of quality.

With websockets, the WebSocket protocol is the whole application surface. You import serve, you get connections, and you write the logic that consumes them. There is no routing layer, no middleware stack and no HTTP application to mount. That makes the library a good fit for a dedicated service, a bot, an internal tool or a test harness where the WebSocket endpoint is the product.

With uvicorn, the WebSocket endpoint is one route among many in an ASGI application. You get HTTP handling, lifespan events and a deployment story shared with the rest of your web service, at the cost of an additional framework layer and its own upgrade cadence. Sanic is the other name the README gives, and it follows the same pattern: a web framework that supports WebSocket connections by building on websockets.

The decision rule that falls out of this is narrow. If your program is a WebSocket server, use websockets. If your program is a web application that also needs a WebSocket endpoint, use a server that builds on it.

Maintenance, releases and upgrade cost

The repository is not archived, and its last push was on 2026-09-20, two days before this writing. Recent releases are 17.1 on 2026-08-26, 17.0.1 on 2026-07-31 and 17.0 on 2026-07-29. The cadence is regular and the version numbers move fast, which matters for upgrade planning: the gap between 17.0 and 17.1 is under a month.

That pace has a cost. A library that ships major versions frequently is a library whose API can move, and the README already shows two distinct import paths, websockets.asyncio.server and websockets.sync.client, alongside a legacy implementation that the repository keeps in example/legacy and that the Makefile still carries a workaround for. The changelog link in pyproject.toml points at https://websockets.readthedocs.io/en/stable/project/changelog.html, and that is the file to read before pinning a version in a lockfile.

On licensing, the project is released under the BSD license, and pyproject.toml records the SPDX identifier as BSD-3-Clause. That is a permissive license, which generally means you can use, modify and redistribute the library with the copyright notice and disclaimer preserved, but the details belong to your own legal review rather than to this article. The README also notes that the maintainers offer commercial support and a security contact through the Tidelift subscription, which is a separate arrangement from the license.

Editorial conclusion

Adopt websockets when you need a correct RFC 6455 implementation in Python and your application logic is already asynchronous or can be made so. Do not adopt it if you need callbacks instead of coroutines, or if you want one server that serves both a full HTTP application and WebSocket upgrades: the README states its HTTP support is minimal, just enough for a health check, and points at uvicorn or Sanic for that combination. Before committing, verify that your Python is 3.11 or later, that your runtime can load the pre-compiled speedups wheel or build the C extension, and that your deployment tolerates a process that is pinned to a single asyncio event loop.

Frequently asked questions

How do I install websockets in Python?

Install it from PyPI with pip install websockets. The package requires Python 3.11 or later, as declared in pyproject.toml under requires-python.

How do I use websockets in Python?

The README's example defines an async echo function that iterates over the connection and sends each message back, then calls serve(echo, "localhost", 8765) and awaits serve_forever. A client can connect with the threading API through websockets.sync.client.connect.

How do I install websockets?

The package name on PyPI is websockets, so the install command is pip install websockets. The project also registers a console script named websockets via the [project.scripts] entry in pyproject.toml.

Official sources

  1. License: BSD-3-Clause
  2. Project website
  3. python-websockets/websockets on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/python-websockets-websockets.svg)](https://hysenlabs.com/projects/python-websockets-websockets)