TwitchIO: an async Python library for the Twitch API, EventSub and chat bots
A fully featured, powerful async Python library for the Twitch API and EventSub.
At a glance
- What is it?
- TwitchIO is a Python library for the Twitch API and EventSub built around asyncio and stateful objects, with chat command extensions, scheduled routines, overlay support with hot-reloadable modules, and built-in OAuth token management including the device code flow. It ships a single runtime dependency, aiohttp, and requires Python 3.11 or newer.
- Who is it for?
- TwitchIO suits a developer building a Twitch bot, an overlay or a Twitch-adjacent backend who wants one async library covering chat, EventSub and the REST API rather than three, and the extension system with hot-reloadable modules is what makes a live overlay workable. It does not suit a project that only needs to publish a few API calls, since the object model and the client machinery are the cost of admission, and it does not suit a team that wants to avoid asyncio.
- Can I use it commercially?
- Yes. MIT 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 17 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 October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One library for the REST API, chat and EventSub
TwitchIO is described as a fully featured, powerful async Python library for the Twitch API and EventSub with modern object-oriented design and stateful objects, and the repository description calls it a powerful asynchronous Python library for twitch.tv.
The scope is what makes it worth the dependency. The README lists the feature set and it is specific rather than promotional.
Modern async Python using asyncio, with the package fully annotated and complying with the pyright strict type-checker. Conduit support for scaling and EventSub continuity. Feature-full including extensions for chat bots, running routine tasks and overlays on stream. Easy management of OAuth tokens and the device code flow with built-in token management. And built-in EventSub support via Webhook, Websockets and Conduits.
That last point is the one that needs unpacking, because it is a choice rather than a feature list. EventSub is Twitch's subscription mechanism for events, and it can be delivered three ways. A Webhook posts to an endpoint you expose, a Websocket keeps a connection open per subscriber, and a Conduit is a server-side multiplexer that Twitch maintains on your behalf so many subscribers share one connection. Conduit support is the scaling answer, and it is also why the library carries the words for EventSub continuity.
The rest of the framework follows from the same aim. The README frames it as providing ease of use when accessing the Twitch API with powerful extensions for chat commands, web frameworks and overlays with hot-reloadable modules, to help create and manage bots, backends, websites and other applications on Twitch.
So the audience is broader than bot authors. A website that shows live chat, a stream overlay, a backend that reacts to subscriptions, and a chat bot are all the same library seen from different angles.
The package layout mirrors the four things a Twitch app does
The setuptools configuration in pyproject.toml lists the subpackages explicitly, and the list is a good map of the library.
packages = [
"twitchio",
"twitchio.models",
"twitchio.eventsub",
"twitchio.authentication",
"twitchio.web",
"twitchio.ext.commands",
"twitchio.ext.routines",
"twitchio.types_",
]twitchio.models holds the domain objects, the users, channels, streams, subscriptions and clips you work with as instances rather than as dictionaries. twitchio.eventsub holds the subscription layer, with the webhook, websocket and conduit implementations. twitchio.authentication is the OAuth and token layer, including the device code flow. twitchio.web is the HTTP layer for talking to the Twitch API, which is where aiohttp comes in.
Then the two extension packages, and these are the ones that make it a bot framework rather than an API client. twitchio.ext.commands is the chat command system, and twitchio.ext.routines is the scheduled task runner.
The types_ package with a trailing underscore is a small detail that saves a name collision. Python has no package named types, because types is a standard library module, so the underscore suffix avoids shadowing it.
The package data configuration adds py.typed to the twitchio package, which is the marker file that tells type checkers the package ships inline annotations. Combined with the strict pyright badge, this is a library where the type information is part of the contract rather than an afterthought.
The twing extension packages also explain the repository layout: examples/ contains basic_bot/, basic_conduits/, basic_routines/, device_code_flow/ and module_examples/, so each of those claims in the feature list has a runnable directory behind it.
One dependency, and a version scheme that encodes the commit
The runtime dependency list is one line.
aiohttp>=3.9.1,<4That is the whole of requirements.txt, and the dependency section in pyproject.toml is dynamic, read from that file. For a library that talks to a REST API, maintains websockets and handles OAuth, having aiohttp as the only third party dependency is a strong signal about how much the library does itself rather than delegating to a stack of helper packages.
The setup.py file is unusual and worth understanding, because it explains the release numbering. It reads twitchio/__init__.py with a regular expression to find the __version__ string, and raises a RuntimeError if the version is not set. Then it checks whether the version ends with dev, a, b or rc, and if so appends a commit count taken from git rev-list --count HEAD.
So a development or pre-release build carries a suffix with the number of commits since the tag. That gives every build from a branch a distinct, comparable version string, which is exactly what you want when you are deploying a specific commit rather than a release.
The packaging metadata is otherwise conventional: setuptools with the wheel backend, dynamic version and dependencies, and a MIT licence classifier. The readme lists Python 3.11, 3.12 and 3.13 as classifiers, and requires-python is set to >=3.11, with the readme badge naming 3.11 through 3.14.
The optional dependency groups are the interesting part for an adopter. docs pulls in Sphinx with the wagtail theme and a set of extensions including sphinxcontrib-asyncio and sphinxcontrib-trio. starlette pulls in starlette>=1.0.0 and uvicorn, which is the web framework integration. dev pins ruff at 0.11.2, pyright at 1.1.402 and isort, so the tooling versions are pinned rather than ranged.
What the extensions are actually for
The two extension packages are where the difference between an API client and a bot framework shows, and the examples directory is the guide to them.
The commands extension is the chat command layer. A Twitch bot that accepts commands from chat needs to parse a prefix, dispatch to a handler, and produce a reply, and it needs to do that without blocking the event loop that is also handling EventSub traffic. The commands extension is listed separately in the package list, which means it is a layer you can adopt or not.
The routines extension is the scheduler. Routine tasks are the recurring work a bot does on a timer, and the reason they are a separate module rather than a helper in the core is that a scheduler is a lifecycle concern. It has to start, stop and clean up with the client.
The module_examples directory is the one that matters most for overlays, and the phrase hot-reloadable modules in the README is doing real work there. An overlay is a web page that a streamer displays on their stream, and the usual development loop for one is painful: change a template, reload the browser, wait for the stream to pick it up. If the module can be reloaded without restarting the bot, the loop becomes the same as any web development loop.
The starlette optional dependency exists for the same reason. The web layer in twitchio.web handles the API, but an overlay served to a browser needs an HTTP server, and the starlette extra gives you starlette and uvicorn without asking you to pick a web framework the library did not choose for you.
What the library does not appear to do is host a web application for you. The extensions are for code running in your bot process, and the overlay support means hot-reloading modules inside that process, not serving the overlay itself.
Where TwitchIO is the wrong choice
Three cases, and they are worth separating because they look similar from the outside.
The first is a project that only needs to read from the Twitch API. If you want to look up a channel's follower count once an hour, pulling in a library with a models layer, an EventSub layer with three transports, an authentication layer, a commands extension and a routines extension is a lot of surface for one HTTP call. The requests library with the Twitch API documentation open is a smaller commitment.
The second is a synchronous codebase. The library is built on asyncio and every entry point is a coroutine, which means it cannot be dropped into a synchronous application without an event loop to run it in. If your existing service is a traditional request handler or a worker with a blocking loop, adopting TwitchIO means either converting that path or running the bot as a separate process and talking to it.
The third is the EventSub transport choice, and it is a real commitment rather than a configuration detail. Webhook delivery means you expose an endpoint and handle the verification and notification flow yourself, with whatever web server you already run. Websocket delivery means the library maintains a connection and you handle reconnection. Conduit delivery means Twitch multiplexes on your behalf and you manage conduit sessions and subscriptions through the API. Each has different operational consequences, and the README lists all three without recommending one, so the choice falls to you and it affects how your bot fails when the network misbehaves.
The alternatives differ in what they assume. A raw HTTP client with the Twitch API documentation gives you no EventSub, no chat parsing and no token management, and nothing else to maintain. The Twitch official Helix examples show the protocol but not a framework. And a chat-only library leaves you to wire EventSub yourself, which for a bot that needs to react to subscriptions is most of the work.
Editorial conclusion
TwitchIO suits a developer building a Twitch bot, an overlay or a Twitch-adjacent backend who wants one async library covering chat, EventSub and the REST API rather than three, and the extension system with hot-reloadable modules is what makes a live overlay workable. It does not suit a project that only needs to publish a few API calls, since the object model and the client machinery are the cost of admission, and it does not suit a team that wants to avoid asyncio. Before adopting it, check that the event types you need are covered by your EventSub subscription type, since Webhook, Websocket and Conduit are alternatives rather than a single combined mode, and read the changelog for the version you pin because the release line is at 3.3.x and the API surface has moved across those minors.
Frequently asked questions
What does TwitchIO provide for the Twitch API and EventSub?
It is an async Python library for the Twitch API and EventSub with built-in EventSub support via Webhook, Websockets and Conduits, plus extensions for chat bots, routine tasks and overlays with hot-reloadable modules. It also includes built-in OAuth token management and the device code flow.
What are TwitchIO's runtime dependencies and Python requirement?
The runtime dependency list is a single package, aiohttp>=3.9.1,<4, read dynamically from requirements.txt. The package requires Python >=3.11, with classifiers for 3.11 through 3.13 and a readme badge naming 3.11 through 3.14.
What do the TwitchIO extension packages do?
twitchio.ext.commands provides the chat command layer and twitchio.ext.routines provides the scheduled task runner. The package list also includes twitchio.models, twitchio.eventsub, twitchio.authentication, twitchio.web and twitchio.types_, and the examples directory contains a basic_bot, basic_conduits, basic_routines, device_code_flow and module_examples.
How does TwitchIO handle development version numbers?
The setup.py file reads the __version__ string from twitchio/__init__.py and, if it ends with dev, a, b or rc, appends the commit count from git rev-list --count HEAD. That gives each branch build a distinct version string, and it raises a RuntimeError if no version is set.
What licence does TwitchIO use and what is its release history like?
MIT, with the MIT classifier in the package metadata and a LICENSE file at the repository root. The recent releases are 3.3.0 on 2026-08-03, 3.3.1 on 2026-08-04 and 3.3.2 on 2026-08-04, with the last push on 2026-10-06. The project runs on pyright strict and pins ruff at 0.11.2 and pyright at 1.1.402 in its dev group.
Official sources
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.
[](https://hysenlabs.com/projects/twitchio-twitchio)Was this useful?