ytdlbot: a Telegram bot that fetches videos for you
Download videos from Youtube and other platforms through a Telegram Bot
At a glance
- What is it?
- ytdlbot turns a Telegram chat into a media downloader: send it a link and it fetches the video with yt-dlp, aria2 or requests, then uploads the file back, with a cache, quality selection and a per-user daily quota.
- Who is it for?
- ytdlbot fits a self-hosting operator who wants media downloads delivered inside Telegram rather than through a browser, and it fits groups that want one shared bot instead of every member installing a downloader.
- Can I use it commercially?
- Yes. Apache-2.0 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?
- Activity is slowing. The repository last received commits 6 months 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 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The chat message is the whole interface
ytdlbot is a Telegram bot for downloading videos from YouTube and other supported websites, and the interaction is deliberately minimal. You send a link directly to the bot and it replies with the media. There is no web interface to learn and no local client to install, which is the appeal for anyone who wants to pull a file from a phone or from a shared group chat. The bot covers YouTube and, in effect, anything yt-dlp supports, plus a separate command for specific link downloaders aimed at Instagram, Pixeldrain and KrakenFiles. The command list is short and fixed: start, about, help, spdl, direct, ytdl, settings, unsub, ping, stats and buy. Two of those are worth noting for a group deployment. ytdl downloads a video in a group, and settings sets your own preferences.
Three download engines and a cache that avoids refetching
Under the bot there are three ways to move bytes, and the project exposes all of them rather than picking one. The main path uses yt-dlp, with aria2 available as an alternative engine and requests as a third. The direct command is the entry point for the aria2 and requests engines, while ytdl covers the standard flow. The dependency list pins the stack closely: yt-dlp with the curl-cffi extra is held at version 2026.1.31, redis is pinned to 6.4.0 and psutil to 7.2.2, with APScheduler, tqdm for progress bars, ffmpeg-python and ffpb for media work, PyMySQL and SQLAlchemy for storage, cryptography, beautifulsoup4, filetype and token-bucket for rate limiting. The cache mechanism is the part that matters for a shared instance: download once for the same video and reuse it, so the second requester does not pay the bandwidth cost again.
Every capability of the bot is switched on from .env
The configuration file is where the real behaviour lives, and it is deliberately explicit about what is required and what is optional. Required keys are WORKERS for the number of workers, APP_ID, APP_HASH, BOT_TOKEN, OWNER and AUTHORIZED_USER as comma separated lists of Telegram ids, DB_DSN for a MySQL URL or a SQLite path, and REDIS_HOST. Optional keys control the features: ENABLE_FFMPEG and ENABLE_ARIA2 switch the media and download engines on, AUDIO_FORMAT sets the desired audio format such as mp3 or wav, RCLONE_PATH points at the Rclone executable, ENABLE_VIP and PROVIDER_TOKEN enable the paid tier through Stripe, FREE_DOWNLOAD sets the free downloads allowed per user and RATE_LIMIT caps request frequency. There are also TG_NORMAL_MAX_SIZE for the Telegram upload ceiling in megabytes, CAPTION_URL_LENGTH_LIMIT, TMPFILE_PATH for temporary files, POTOKEN and BROWSERS for cookie-based handling.
Three ways to install it, one image
The project says the bot can be deployed on any platform that supports Python, and it documents a native path and a container path. Dependencies are managed with PDM, which you can install with pip.
pip install --user pdmThen the environment itself comes from one of two commands.
pdm install
pip install -r requirements.txtThe first is the PDM route, the second is the older requirements.txt route that the project keeps around for people who do not want PDM. Before starting, copy the example configuration and edit it.
cp .env.example .envThen activate the environment and run the bot.
source .venv/bin/activate
python src/main.pyThe container route is a single command, since a Docker image is published.
docker run --env-file .env bennythink/ytdlbotThe image is built from python:3.12-alpine and installs ffmpeg, aria2 and deno in the runner stage, which covers the media tooling and the JavaScript runtime that yt-dlp needs for YouTube.
Redis and MySQL are not optional in the compose file
The bundled docker-compose.yml makes the infrastructure requirement plain. It defines three services: a redis service on the redis:7-alpine image with a healthcheck that runs redis-cli ping, a mysql service on ubuntu/mysql:8.0-22.04_beta with a persistent ./db_data volume, utf8mb4 character set, a 64M max_allowed_packet and native password authentication, and the ytdlbot service itself built from the bennythink/ytdlbot image. The bot service waits for both redis and mysql to report healthy before it starts, which is the right ordering for a bot that opens a database connection and a cache on boot. The compose file also mounts ./youtube-cookies.txt into the container at /app/youtube-cookies.txt, so cookie-based access to YouTube survives container restarts. If you already run Redis and MySQL, you can point DB_DSN and REDIS_HOST at your own instances and run only the bot container.
The JS runtime warning is the one that bites YouTube
A note dated in the project documents says that all users who intend to download from YouTube are strongly encouraged to install one of the JS runtimes supported by yt-dlp, with deno given as the example. That advice matters because YouTube changed how it serves media, and a downloader without a JavaScript runtime can fail to extract the formats it needs even though nothing else about the setup is wrong. The Docker image already installs deno for you, so the native install is where this bites. If you deploy natively and YouTube downloads fail while other sites work, that missing runtime is the first thing to check. The same reasoning applies to POTOKEN, which the configuration exposes with a link to the yt-dlp PO Token guide, and to BROWSERS, which names the browser used to handle cookies from browser.
Quotas, VIP and the Stripe path for a self-hosted operator
The free public instances run a quota system, and the project describes it plainly: because of limitations on servers and bandwidth, each user is limited to one free download per day on the free service. The same concept is a configuration knob for your own deployment. FREE_DOWNLOAD sets how many free downloads a user gets, RATE_LIMIT caps request rate, and TG_NORMAL_MAX_SIZE sets the maximum Telegram upload size in megabytes, which is the practical ceiling on how large a file can come back through the chat. The paid path exists too: ENABLE_VIP turns on the VIP features and PROVIDER_TOKEN carries the Stripe payment provider token, and the buy command buys quota. For a self-hosted operator, that means the bot can be a public service with metered access rather than an open relay, or it can be an internal tool with the limits turned up.
Packaging details that show how the project is maintained
The repository layout gives a clear picture of how the bot is assembled. There is a src/ directory holding the application code, a pyproject.toml that declares the project as ytdlbot version 1.0.0 with Apache2.0 licensing and a requires-python floor of >=3.10, a pdm.lock alongside a requirements.txt for the two install paths, and a Dockerfile and docker-compose.yml for the container route. Distribution is set to false under the PDM configuration, meaning this is an application rather than a library to publish on an index. A pre-push.py script sits at the root, and there is a Dockerfile workflow badge for the image build. The project ships no GitHub releases at all, and the last push to the repository was on 2026-04-22, so the tree you clone is the artefact to judge, not a tagged build.
Editorial conclusion
ytdlbot fits a self-hosting operator who wants media downloads delivered inside Telegram rather than through a browser, and it fits groups that want one shared bot instead of every member installing a downloader. It does not fit anyone who needs unlimited throughput, because the public instances limit each user to one free download per day and the free allowance is a configurable value you would have to raise yourself, and it does not fit an operator who expects a polished release stream, since the project publishes no GitHub releases and the last push was on 2026-04-22. Before you deploy, copy .env.example to .env and fill in BOT_TOKEN, APP_ID, APP_HASH and DB_DSN, decide whether Redis and MySQL come from the bundled docker-compose.yml or from your own infrastructure, and check that you have a JS runtime such as deno available for YouTube, as the project warns.
Frequently asked questions
How do I run ytdlbot on my own machine?
Install PDM with pip install --user pdm, run pdm install, copy the example config with cp .env.example .env and fill in the required fields, then activate the virtual environment with source .venv/bin/activate and start the bot with python src/main.py. A Docker image is also published for a one-line start.
Which databases and services does ytdlbot need?
The bundled docker-compose.yml defines redis, mysql and the bot itself, and the bot waits for both to become healthy before starting. In configuration terms you need a DB_DSN pointing at a MySQL URL or a SQLite path, plus REDIS_HOST.
Why do YouTube downloads fail while other sites work?
The project warns that you should install a JavaScript runtime supported by yt-dlp, with deno as the example, when downloading from YouTube. The Docker image installs deno already, so a native install is where this usually goes missing.
How many downloads does a user get for free?
On the free public service each user is limited to one free download per day, because of server and bandwidth limits. When you host it yourself, FREE_DOWNLOAD sets the number of free downloads allowed per user and RATE_LIMIT caps the request rate.
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/tgbot-collection-ytdlbot)Was this useful?