websockets

licence version pyversions tests docs openssf

websockets is a library for building WebSocket servers and clients in Python with a focus on correctness, simplicity, robustness, and performance.

It supports several network I/O and control flow paradigms.

  1. The default implementation builds upon asyncio, Python’s built-in asynchronous I/O library. It provides an elegant coroutine-based API. It’s ideal for servers that handle many client connections.

  2. The threading implementation is a good alternative for clients, especially if you aren’t familiar with asyncio. It may also be used for servers that handle few client connections.

  3. The Sans-I/O implementation is designed for integrating in third-party libraries, typically application servers, in addition being used internally by websockets.

Refer to the feature support matrices for the full list of features provided by each implementation.

The asyncio implementation was rewritten.

The new implementation in websockets.asyncio builds upon the Sans-I/O implementation. It adds features that were impossible to provide in the original design. It was introduced in version 13.0.

The historical implementation in websockets.legacy traces its roots to early versions of websockets. While it’s stable and robust, it was deprecated in version 14.0 and it will be removed by 2030.

The new implementation provides the same features as the historical implementation, and then some. If you’re using the historical implementation, you should ugrade to the new implementation.

Here’s an echo server and corresponding client.

#!/usr/bin/env python

"""Echo server using the asyncio API."""

import asyncio
from websockets.asyncio.server import serve


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


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


if __name__ == "__main__":
    asyncio.run(main())
#!/usr/bin/env python

"""Echo server using the threading API."""

from websockets.sync.server import serve


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


def main():
    with serve(echo, "localhost", 8765) as server:
        server.serve_forever()


if __name__ == "__main__":
    main()
#!/usr/bin/env python

"""Client using the asyncio API."""

import asyncio
from websockets.asyncio.client import connect


async def hello():
    async with connect("ws://localhost:8765") as websocket:
        await websocket.send("Hello world!")
        message = await websocket.recv()
        print(message)


if __name__ == "__main__":
    asyncio.run(hello())
#!/usr/bin/env python

"""Client using the threading API."""

from websockets.sync.client import connect


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


if __name__ == "__main__":
    hello()

Don’t worry about the opening and closing handshakes, pings and pongs, or any other behavior described in the WebSocket specification. websockets takes care of this under the hood so you can focus on your application!

Also, websockets provides an interactive client:

$ python -m websockets ws://localhost:8765/
Connected to ws://localhost:8765/.
> Hello world!
< Hello world!
Connection closed: 1000 (OK).

Do you like it? Let’s dive in!