A personal Telegram bot that accepts YouTube URLs in a private chat, downloads the best video+audio format that fits under 12 MB, and sends the file back to you — all without leaving Telegram.
The bot is designed for a single user. It ignores every message that does not come from your configured Telegram user ID.
- Send a YouTube URL to your bot in Telegram.
- The bot fetches video metadata, picks the best format under the size limit, and queues the download.
- It reports progress as it goes ("Downloading… 480p, ~8.1 MB", "Uploading…").
- The finished video lands in your chat.
Multiple URLs are queued and processed one at a time so the server is never overwhelmed.
| Requirement | Notes |
|---|---|
| A Linux server (Debian/Ubuntu recommended) | Needs to be online to receive Telegram updates |
ffmpeg |
Used to mux separate video/audio streams into a single .mp4 |
| A Telegram account | To create the bot and find your user ID |
| Go 1.22+ | Only needed if building from source |
yt-dlp does not need to be installed manually — the bot downloads it
automatically on first run.
-
Open Telegram and start a chat with @BotFather.
-
Send
/newbot. -
Choose a display name (e.g.
My Download Bot) and a username ending inbot(e.g.mydownload_bot). -
BotFather replies with a token that looks like:
5555555555:AAFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKeep this token secret. Anyone who has it can control your bot.
-
Optionally send
/setprivacy→ select your bot → Disable so the bot can read messages in groups if you ever need that. For a private bot the default (enabled) is fine.
The bot only responds to one user. You need your numeric user ID (not your username).
- Start a chat with @userinfobot and send any message.
- It replies with your ID, e.g.
Id: 123456789. - Note this number — you will put it in the config as
allowed_user_id.
# Install build dependencies
sudo apt-get install golang ffmpeg dpkg-dev debhelper
# Clone and build
git clone https://github.com/penguinpowernz/ytdlbot
cd ytdlbot
make deb
# Install the package (adjust filename for your arch/version)
sudo dpkg -i ../ytdlbot_1.0.0-1_amd64.deb
sudo apt-get install -f # installs ffmpeg if not already presentThe package creates a ytdlbot system user, installs the binary to
/usr/bin/ytdlbot, and places a template config at /etc/ytdlbot/config.yaml.
sudo apt-get install golang ffmpeg
git clone https://github.com/penguinpowernz/ytdlbot
cd ytdlbot
make build # produces ./bin/ytdlbot
# Create directories
sudo mkdir -p /var/lib/ytdlbot/bin /etc/ytdlbot
# Copy the example config
sudo cp config.example.yaml /etc/ytdlbot/config.yaml
sudo chmod 600 /etc/ytdlbot/config.yamlEdit /etc/ytdlbot/config.yaml:
bot_token: "5555555555:AAFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
allowed_user_id: 123456789
work_dir: /var/lib/ytdlbot
yt_dlp_path: /var/lib/ytdlbot/bin/yt-dlp
ffmpeg_path: /usr/bin/ffmpeg
max_file_bytes: 12582912 # 12 MB — Telegram Bot API hard limit
max_duration_seconds: 300 # reject videos longer than 5 minutes
disk_warn_bytes: 524288000 # warn in chat when < 500 MB free on disk
queue_depth: 20 # max number of jobs waiting at once- Set
bot_tokento the token from BotFather. - Set
allowed_user_idto the number from Step 2. - Leave everything else at the defaults unless you have a reason to change it.
The config file contains your bot token, so permissions matter:
sudo chmod 600 /etc/ytdlbot/config.yaml
sudo chown ytdlbot:ytdlbot /etc/ytdlbot/config.yaml # if using the packagesudo systemctl enable --now ytdlbot
sudo systemctl status ytdlbotThe service starts automatically on boot and restarts itself if it crashes.
./bin/ytdlbot -c /etc/ytdlbot/config.yamlOn the very first start, if yt-dlp is not present at yt_dlp_path, the bot
downloads it automatically from the official GitHub releases before accepting
any URLs. You will see log output like:
{"level":"INFO","msg":"yt-dlp not found, attempting bootstrap","path":"/var/lib/ytdlbot/bin/yt-dlp"}
{"level":"INFO","msg":"yt-dlp bootstrapped successfully","path":"/var/lib/ytdlbot/bin/yt-dlp"}
If the download fails (e.g. no internet at startup), the bot still starts but
disables URL handling and sends you a Telegram message explaining the problem.
Run /updateytdlp to retry.
- Open Telegram and find the bot you created in Step 1 (search for its username).
- Send
/start— the bot should reply with a welcome message. - Send a short YouTube URL. The bot will reply "✅ Queued. Position: 1" and then send progress updates as it downloads and uploads the video.
If the bot does not reply to /start, check the logs:
sudo journalctl -fu ytdlbot| Command | What it does |
|---|---|
/start |
Welcome message with usage instructions |
/help |
List all commands |
/queue |
Show what is currently downloading and what is waiting |
/cancel |
Cancel the last queued job that has not started yet |
/updateytdlp |
Download or update yt-dlp to the latest release |
YouTube changes its format regularly and yt-dlp releases updates to keep up.
Send /updateytdlp in chat at any time — the bot will download the latest
release and report the result. No restart needed.
# Follow live logs (systemd)
sudo journalctl -fu ytdlbot
# Show the last 100 lines
sudo journalctl -u ytdlbot -n 100Logs are JSON (structured), which makes them easy to search:
sudo journalctl -u ytdlbot | grep '"level":"WARN"'Bot does not reply at all
- Confirm the
bot_tokenin the config is correct. - Check that the server can reach
api.telegram.org(firewall / DNS). - Check logs:
sudo journalctl -fu ytdlbot.
"unauthorized user" in logs but it is you sending the message
- Your
allowed_user_idis wrong. Double-check it with @userinfobot — it must be a number, not a username.
"yt-dlp or ffmpeg is missing" message in chat
ffmpeg:sudo apt-get install ffmpeg, then restart the bot.yt-dlp: send/updateytdlpand the bot will download it. If that fails, check thatwork_diris writable by theytdlbotuser.
"Queue is full"
- Lower
queue_depthis not the issue — the queue is simply at capacity. Wait for current downloads to finish. The default of 20 is generous for a personal bot.
Video is too large
- The bot tries every available format from largest to smallest until one fits
under
max_file_bytes. If the smallest format still exceeds the limit, it reports the actual size. You can raisemax_file_bytesbut Telegram's Bot API hard limit is 50 MB for uploads; the default 12 MB matches Telegram's client-side sending limit for most clients.
make build # compile binary to ./bin/ytdlbot
make test # run unit tests
make vet # run go vet
make lint # run go vet + staticcheck
make deb # build installable .deb package
make clean # remove ./bin/Requires a real bot token and Telegram account:
YTDLBOT_TOKEN=<token> \
YTDLBOT_USER_ID=<your_user_id> \
YTDLBOT_CHAT_ID=<chat_id> \
./scripts/integration_test.shThe script starts the bot, sends a short public-domain video URL, and asserts that a video message is received back within 120 seconds.