Features

Feature support matrices summarize which implementations support which features.

Both sides

asyncio (new)

threading

trio

Sans-I/O

asyncio (legacy)

Perform the opening handshake

✅

✅

✅

✅

✅

Enforce opening timeout

✅

✅

✅

—

✅

Send a message

✅

✅

✅

✅

✅

Broadcast a message

✅

✅

✅

—

✅

Receive a message

✅

✅

✅

✅

✅

Iterate over received messages

✅

✅

✅

—

✅

Send a fragmented message

✅

✅

✅

✅

✅

Receive a fragmented message frame by frame

✅

✅

✅

—

❌

Receive a fragmented message after reassembly

✅

✅

✅

—

✅

Force sending a message as Text or Binary

✅

✅

✅

—

❌

Force receiving a message as bytes or str

✅

✅

✅

—

❌

Send a ping

✅

✅

✅

✅

✅

Respond to pings automatically

✅

✅

✅

✅

✅

Send a pong

✅

✅

✅

✅

✅

Keepalive

✅

✅

✅

—

✅

Heartbeat

✅

✅

✅

—

✅

Measure latency

✅

✅

✅

—

✅

Perform the closing handshake

✅

✅

✅

✅

✅

Enforce closing timeout

✅

✅

✅

—

✅

Report close codes and reasons from both sides

✅

✅

✅

✅

❌

Compress messages (RFC 7692)

✅

✅

✅

✅

✅

Tune memory usage for compression

✅

✅

✅

✅

✅

Negotiate extensions

✅

✅

✅

✅

✅

Implement custom extensions

✅

✅

✅

✅

✅

Negotiate a subprotocol

✅

✅

✅

✅

✅

Enforce security limits

✅

✅

✅

✅

✅

Log events

✅

✅

✅

✅

✅

Server

asyncio (new)

threading

trio

Sans-I/O

asyncio (legacy)

Listen on a TCP socket

✅

✅

✅

—

✅

Listen on a Unix socket

✅

✅

❌

—

✅

Listen using a preexisting socket

✅

✅

✅

—

✅

Encrypt connection with TLS

✅

✅

✅

—

✅

Close server on context exit

✅

✅

✅

—

✅

Close connection on handler exit

✅

✅

✅

—

✅

Shut down server gracefully

✅

✅

✅

—

✅

Check Origin header

✅

✅

✅

✅

✅

Customize subprotocol selection

✅

✅

✅

✅

✅

Configure Server header

✅

✅

✅

✅

✅

Alter opening handshake request

✅

✅

✅

✅

❌

Alter opening handshake response

✅

✅

✅

✅

❌

Force an HTTP response

✅

✅

✅

✅

✅

Perform HTTP Basic Authentication

✅

✅

✅

❌

✅

Dispatch connections to handlers

✅

✅

✅

—

❌

Client

asyncio (new)

threading

trio

Sans-I/O

asyncio (legacy)

Connect to a TCP socket

✅

✅

✅

—

✅

Connect to a Unix socket

✅

✅

✅

—

✅

Connect using a preexisting socket

✅

✅

✅

—

✅

Encrypt connection with TLS

✅

✅

✅

—

✅

Close connection on context exit

✅

✅

✅

—

✅

Reconnect automatically

✅

✅

✅

—

✅

Configure Origin header

✅

✅

✅

✅

✅

Configure User-Agent header

✅

✅

✅

✅

✅

Modify opening handshake request

✅

✅

✅

✅

✅

Modify opening handshake response

✅

✅

✅

✅

❌

Connect to non-ASCII IRIs

✅

✅

✅

✅

✅

Follow HTTP redirects

✅

✅

✅

—

✅

Perform HTTP Basic Authentication

✅

✅

✅

✅

✅

Connect via HTTP proxy

✅

✅

✅

—

❌

Connect via SOCKS5 proxy

✅

✅

✅

—

❌

Known limitations

There is no way to control compression of outgoing frames on a per-frame basis (#538). If compression is enabled, all frames are compressed.

The server doesn’t check the Host header and doesn’t respond with HTTP 400 Bad Request if it is missing or invalid (#1246).

The client doesn’t support HTTP Digest Authentication (#784).

The client API doesn’t attempt to guarantee that there is no more than one connection to a given IP address in a CONNECTING state. This behavior is mandated by RFC 6455, section 4.1. However, connect() isn’t the right layer for enforcing this constraint. It’s the caller’s responsibility.

It is possible to send or receive a text message containing invalid UTF-8 with send(not_utf8_bytes, text=True) and not_utf8_bytes = recv(decode=False) respectively. As a side effect of disabling UTF-8 encoding and decoding, these options also disable UTF-8 validation.