twitch-dl pulls Twitch VODs and clips with parallel connections
CLI tool for downloading videos from Twitch.
At a glance
- What is it?
- twitch-dl is a Python command line tool for downloading videos and clips from twitch.tv, inspired by youtube-dl but using multiple concurrent connections to speed up transfers. It is published on PyPI, requires Python 3.9 and ffmpeg, and can also be run as a self-contained zipapp.
- Who is it for?
- twitch-dl suits someone who wants to keep a copy of a publicly available Twitch broadcast or clip on their own disk, since it handles the listing, the HLS download and the muxing without a browser, and the concurrent connections make long VODs quicker to pull. It is the wrong tool if you need scheduled archiving, or a full media library manager, because the README lists none of that.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 61 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A youtube-dl shape for Twitch
twitch-dl is a CLI tool for downloading videos from twitch.tv, and its lineage is stated in the README: inspired by youtube-dl, but improving upon it by using multiple concurrent connections to make the download faster.
That single design decision is the whole differentiator, and it is aimed at a specific pain. A Twitch VOD is a long file served over HLS as a sequence of segments, and a single stream client fetching them in sequence leaves most of the connection idle. Opening several connections at once is what turns a slow transfer into a quick one, and it is why the tool can claim speed without pretending to have a better source of the video.
The command surface follows the same idea as youtube-dl. There are listing commands for videos and clips, and a download command that takes a URL, an ID or a slug. The topics on the repository are simply cli, download-videos and twitch, and the licence is GPLv3 with the copyright held by Ivan Habunek.
The project is packaged as a Python package called twitch-dl on PyPI, with a console script named twitch-dl, and the documentation lives at twitch-dl.bezdomni.net with separate installation and usage pages.
Listing a channel before you download anything
The quick start starts by listing rather than downloading, which is the sensible order when you are deciding what you actually want.
twitch-dl videos bananasaurus_rexlists videos from a channel, and the companion command does the same for clips:
twitch-dl clips bananasaurus_rexBoth take a channel name, so the first thing to do with the tool is point it at a channel you follow and see what the output looks like before committing to a transfer.
The listing step also matters practically, because Twitch has no stable URL scheme for everything. A VOD has a numeric ID, a clip has a slug, and both can be resolved. Listing gives you the identifiers the download command wants, rather than making you copy URLs out of a browser page.
Downloading by URL, by ID or by slug
The download command accepts all three forms, and the distinction is the only thing to learn before using it.
A video by URL:
twitch-dl download https://www.twitch.tv/videos/1418494769The same video by ID:
twitch-dl download 1418494769And a clip, by URL:
twitch-dl download https://www.twitch.tv/bananasaurus_rex/clip/PlacidColdClipsdadDeIlluminati-hL2s_aLE4CHvVN4Jor by slug:
twitch-dl download PlacidColdClipsdadDeIlluminati-hL2s_aLE4CHvVN4JThe clip slug is the trailing identifier in a Twitch clip URL, so the short form is just that identifier on its own.
Note that the bare ID form is unambiguous for videos while the bare slug form is for clips. Both commands are called download, and the tool works out which it is from the shape of the argument.
The README points to the usage page for the rest of the command line, which is where the options for output paths, formats and quality live.
What the package actually depends on
The dependency list is short and says a lot about the implementation.
dependencies = [
"click>=8.0.0,<9.0.0",
"httpx>=0.17.0,<1.0.0",
"m3u8>=3.0.0,<7.0.0",
"wcwidth>=0.2,<1.0.0"
]click provides the command line parsing. httpx is the HTTP client, which is the component that has to support several simultaneous streams for the concurrent connection approach to work. m3u8 parses the HLS playlist that describes a Twitch stream as a sequence of segments, and wcwidth handles character width, which is there to align the tables the listing commands print in a terminal that may contain wide characters.
There is one more dependency that is not in that list and is not optional in the same way: ffmpeg, installed and on the system path, is listed under Requirements alongside Python 3.9 or later. Twitch delivers HLS, and turning downloaded segments into a single playable file is ffmpeg's job, not Python's.
The chat command is handled separately. An optional extra called chat pulls in pillow and fonttools, and the pyproject explains why it is optional: it is not pure Python, and requiring it prevents distribution of twitch-dl as a pyz archive while keeping it cross-platform.
Three ways to install it, one of them a single file
The README points at the installation instructions on the documentation site, and the packaging metadata shows what those routes look like.
The ordinary route is the PyPI package, with the project name twitch-dl and a console script entry point of twitch-dl = "twitchdl.cli:cli". The package itself is built with setuptools and setuptools_scm, with the version derived from the git tag rather than written by hand, which is why the release numbers in the changelog follow the tag scheme.
The second route is a zipapp, and the Makefile shows exactly how it is put together. The bundle target copies the package entry point, installs the project into that directory, removes the __pycache__ directories, and then runs python -m zipapp with a python interpreter of /usr/bin/env python3 and compression enabled, producing a twitch-dl archive that can be copied around and run anywhere Python exists. The archive is named from git describe, so it carries the version in the filename.
That single file approach has one trade-off worth knowing. Because the chat extra needs pillow and fonttools, which are not pure Python, the project explicitly excludes that extra from the archive build to keep the result cross-platform. In other words, you can have the zipapp or you can have the chat renderer, and the project has chosen to keep the archive portable.
The third route is the documentation site's own guidance, which is the one to follow if you want the pipx or virtual environment setup rather than installing into a system environment.
The project layout and how it is maintained
The repository is set up like a Python project that keeps its documentation next to the code rather than in a separate site repository.
The package lives under twitchdl, with subpackages for twitchdl.commands and twitchdl.chat, and the entry point is twitchdl.cli. The top level also holds a tests directory, a docs directory, a scripts directory, a pyproject.toml, a Makefile and a book.toml, which is the mdbook configuration for the documentation site. There is a twitch-dl.1.scd file, an scdoc source for the manual page, and the Makefile compiles it with scdoc into twitch-dl.1.man.
The toolchain is fairly strict for a small project. Pyright runs in strict type checking mode against Python 3.9, ruff lints with a line length of 100 and a py39 target, flake8 and vermin are in the repository as separate configuration files, and vermin appears in the dependency groups as a minimum version checker.
The docs are generated rather than hand written. The Makefile has a docs target that regenerates the changelog with ./scripts/generate_changelog, writes it to CHANGELOG.md, runs python scripts/generate_docs, and then builds the book with mdbook build. There is a docs-serve target that runs the same generation and serves the book on port 8000, and a docs-deploy target that rsyncs the built book to the documentation host.
The release history is steady, with 3.3.2 on 2026-08-14, 3.3.1 on 2026-01-25 and 3.3.0 on 2025-12-15, and the last push was on 2026-08-23. The pyproject classifies the project as Production/Stable and Operating System Independent.
What it does not do, and what to use instead
twitch-dl does one thing, and there are moments when that is not enough.
There is no scheduling, no library management and no metadata cataloguing. The tool downloads what you name and exits. If you want a subscription that follows a channel and archives every broadcast automatically, this is the wrong shape, and the README does not claim otherwise.
There is also the question of what a stream is worth while it is live. Twitch's own GraphQL interface is the mechanism behind channel listings, and the README links a third party project documenting it along with a page that lists enhanced broadcasting streams, which is the same idea from the opposite direction: finding a better source for the video than the default one. That is the level of tinkering the tool expects you to be comfortable with when something does not work.
For the alternatives the README names, the differences are concrete. TwitchDownloader by lay295 is a separate implementation with its own approach, and yt-dlp carries a Twitch extractor in its own codebase, which means a single yt-dlp install can handle Twitch alongside a very large set of other sites. Where yt-dlp wins is breadth of sites; where twitch-dl wins is that its Twitch handling is the entire point rather than one extractor among many, and that the concurrent connection approach is applied to every transfer it makes.
The practical answer for a Twitch-only workflow is that twitch-dl is the smaller and more focused of the two. The practical answer for a general purpose downloader already in place is that adding a separate tool is rarely worth it.
Editorial conclusion
twitch-dl suits someone who wants to keep a copy of a publicly available Twitch broadcast or clip on their own disk, since it handles the listing, the HLS download and the muxing without a browser, and the concurrent connections make long VODs quicker to pull. It is the wrong tool if you need scheduled archiving, or a full media library manager, because the README lists none of that. Before running it, install ffmpeg and put it on the system path, since the tool depends on it, and decide whether you want the PyPI install or the zipapp, since the chat extra is deliberately excluded from the archive build.
Frequently asked questions
How do I install twitch-dl?
The README points to the installation instructions at twitch-dl.bezdomni.net/installation.html. The package is published on PyPI as twitch-dl with a twitch-dl console script, and the Makefile also builds a single file zipapp bundle with python -m zipapp for use without installing anything.
How do I download a Twitch video with twitch-dl?
Use the download command with a video URL such as twitch-dl download https://www.twitch.tv/videos/1418494769, or with the bare numeric ID, for example twitch-dl download 1418494769. Clips work the same way with a clip URL or with the slug on its own.
Does twitch-dl need ffmpeg?
Yes. The README lists ffmpeg, installed and on the system path, under Requirements alongside Python 3.9 or later. Twitch streams arrive as HLS segments and ffmpeg is what turns them into a single playable file.
What does the chat extra in twitch-dl do?
The optional chat extra pulls in pillow and fonttools, which are not pure Python, and it is kept optional precisely so that twitch-dl can still be distributed as a pyz archive while remaining cross-platform. The pyproject states that making it non-optional prevents the archive distribution.
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/ihabunek-twitch-dl)Was this useful?