Install & Compatibility
Where this runs
tested against v4.13.5 · 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
muslpy 3.10–3.925 runs
installs and imports cleanly · install 0.0s · import 0.358s · 29.5MB
glibcpy 3.10–3.925 runs
installs and imports cleanly · install 2.3s · import 0.323s · 26MB
27MB installed
● package 27MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
Server
✓ import engineio
eio_server = engineio.Server()
For a standard (threaded) Engine.IO server.
AsyncServer
✓ import engineio
eio_server = engineio.AsyncServer()
For an asyncio-based Engine.IO server.
Client
✓ import engineio
eio_client = engineio.Client()
For a standard (threaded) Engine.IO client.
AsyncClient
✓ import engineio
eio_client = engineio.AsyncClient()
For an asyncio-based Engine.IO client.
WSGIApp
✓ from engineio import WSGIApp
To wrap an Engine.IO server instance for WSGI compatibility.
ASGIApp
✓ from engineio import ASGIApp
To wrap an Engine.IO server instance for ASGI compatibility.
This quickstart demonstrates a basic Engine.IO server using the `AsyncServer` with ASGI mode, integrated with `uvicorn`. It defines event handlers for connect, message, and disconnect. A corresponding `AsyncClient` example is commented out, showing how to connect to the server and send/receive messages. Remember to install `uvicorn` and run the server and client in separate processes.
import engineio
import uvicorn
eio = engineio.AsyncServer(async_mode='asgi')
app = engineio.ASGIApp(eio)
@eio.on('connect')
async def connect(sid, environ):
print('connect ', sid)
@eio.on('message')
async def message(sid, data):
print('message ', data)
await eio.send(sid, 'reply from server')
@eio.on('disconnect')
async def disconnect(sid):
print('disconnect ', sid)
# To run the server (requires uvicorn):
# if __name__ == '__main__':
# uvicorn.run(app, host='127.0.0.1', port=5000)
# --- Client Example (run in a separate process/script) ---
# import engineio
# import asyncio
# eio_client = engineio.AsyncClient()
# @eio_client.on('connect')
# async def on_connect():
# print('client connected')
# await eio_client.send('Hello from client!')
# @eio_client.on('message')
# async def on_message(data):
# print('client received: ', data)
# @eio_client.on('disconnect')
# async def on_disconnect():
# print('client disconnected')
# async def start_client():
# await eio_client.connect('http://localhost:5000')
# await eio_client.wait()
# # To run the client:
# # if __name__ == '__main__':
# # asyncio.run(start_client())
Debug
Known issues
breakingEngine.IO v4 introduced major breaking changes, including a reversal of the heartbeat (ping/pong) mechanism (server now pings, client responds), a new packet encoding format, and a reduced default `maxHttpBufferSize` (from 100MB to 1MB). Clients running on Engine.IO v3 will NOT be compatible with servers running on v4, and vice-versa.fixEnsure all clients and servers are upgraded to be compatible with the same Engine.IO protocol version. Review `maxHttpBufferSize` if large payloads are expected.
affects: 4.x.x (from 4.0.0 onwards)
gotchaThe Engine.IO server library is a protocol implementation and requires an underlying asynchronous framework or WSGI/ASGI web server (e.g., `eventlet`, `gevent`, `aiohttp`, `uvicorn`, `tornado`) to function as a complete web application. It does not provide its own standalone web server.fixAlways integrate the `engineio.Server` or `engineio.AsyncServer` instance with a compatible WSGIApp/ASGIApp and run it using an appropriate web server (e.g., `uvicorn`, `gunicorn` with `eventlet`/`gevent` workers). Refer to documentation for framework-specific integration examples.
affects: All versions
gotchaWhen defining event handlers (e.g., with `@eio.on('message')`), avoid using mutable objects (like lists or dictionaries) as default arguments in the handler function signature. These defaults are created once when the function is defined and shared across all calls/sessions, leading to unexpected behavior.fixInitialize mutable default arguments inside the function body if no argument is provided, typically using `None` as the default in the signature: `def my_handler(sid, data, my_list=None): my_list = my_list or []`.
affects: All Python versions
gotchaThe library internally supports a single custom JSON module per process. Attempting to configure multiple custom JSON encoder/decoder modules might lead to unexpected behavior or errors, as documented in recent changes.fixIf custom JSON serialization is needed, configure it globally for your Engine.IO `Server` or `Client` instance once. Avoid overriding it in multiple places or with different modules within the same process.
affects: All versions (documented explicitly in 4.11.x and newer)
deprecatedOlder Python versions (e.g., 3.7, 3.8, 3.9) are being dropped from continuous integration (CI) builds, indicating that while they might still work, active testing and support focus on newer Python versions (3.10+). The `requires_python` specifier is `>=3.8`.fixIt is recommended to use `python-engineio` with Python 3.10 or newer for full compatibility and ongoing support. Upgrade your Python environment if possible.
affects: <4.12.0 (CI dropping support started around this time)
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'engineio'
The 'python-engineio' package is not installed or not accessible in the current Python environment.
fixpip install python-engineio
TypeError: object NoneType can't be used in 'await' expression
An asynchronous function or coroutine from `engineio.async_server` or `engineio.async_client` was called without being `await`ed within an `async` context.
fixEnsure all asynchronous calls, such as `await client.connect(...)` or `await server.attach(...)`, are properly `await`ed within an `async` function.
engineio.exceptions.ConnectionError
The Engine.IO client failed to establish or maintain a connection with the server, often due to a handshake failure, an invalid URL, or a server-side protocol issue.
fixVerify the server's address and port, check server logs for protocol-level errors, ensure the server is running, and confirm network reachability and firewall settings.
ConnectionRefusedError: [Errno 111] Connection refused
The Engine.IO client attempted to connect to a server that was not listening or explicitly rejected the connection at the specified host and port, often due to the server not running.
fixEnsure the Engine.IO server (or the web server hosting it) is actively running and listening on the exact host and port the client is trying to reach, and check for any firewalls blocking the connection.
Upgrade
Version history
4.13.5latest on PyPI · released Aug 12, 2026
Audit
Dependencies
pythonrequiredCore dependency for any Python library.
requestsrequiredUsed for HTTP communication in clients and polling transport.
simple-websocketrequiredDefault WebSocket client implementation.
websocket-clientrequiredAlternative WebSocket client implementation.
aiohttpoptionalOptional, for integrating with aiohttp applications (asyncio driver).
eventletoptionalOptional, for integrating with Eventlet WSGI applications.
geventoptionalOptional, for integrating with Gevent WSGI applications.
gevent-websocketoptionalOptional, for WebSocket support with Gevent.
tornadooptionalOptional, for integrating with Tornado applications (asyncio driver).
uvicornoptionalCommon ASGI server for deploying asyncio Engine.IO applications.
gunicornoptionalCommon WSGI server for deploying standard Engine.IO applications (e.g., with Eventlet/Gevent workers).