Jul 02, 2026
How to Self-Host a Telegram MTProto Proxy to Bypass Network Blocks (2026)
Learn how to build, deploy, and self-host an obfuscated Telegram MTProto proxy using Docker and …
yt-dlp allows you to extract high-quality video and audio files from 1,000+ streaming platforms (YouTube, Twitter/X, Instagram, TikTok, Reddit, Vimeo, and more) directly inside Telegram without advertisements, watermark overlays, or tracking. By running this script on a cheap VPS or home server using systemd or Docker, you gain 24/7 unlimited access to media conversion with zero reliance on sketchy third-party bots.
Public Telegram downloader bots are among the most searched utility bots on the platform. However, public bots often suffer from sudden downtime, aggressive advertising messages, file length restrictions, rate limiting, and privacy concerns. Self-hosting your own Python media downloader bot resolves all of these issues while giving you complete control over video resolution, audio formats, download speed, and storage settings.
In this comprehensive step-by-step tutorial, you will learn how to build, configure, and deploy a production-grade Telegram media downloader bot in 2026 using Python 3.11+, python-telegram-bot (v20+ async framework), and the ultra-powerful yt-dlp library.
While public bots exist, self-hosting provides key advantages for developers, power users, and community administrators:
| Feature | Public Telegram Downloader Bots | Self-Hosted Python + yt-dlp Bot |
|---|---|---|
| Privacy & Security | Logs requested links, IP addresses, and user IDs. | 100% private. Logs remain strictly on your private VPS. |
| Monetization & Ads | Spams sponsored channel joins and popups. | Zero ads, zero sponsored popups, zero spam. |
| Platform Coverage | Limited to specific sites (e.g., YouTube or TikTok only). | Supports 1,000+ platforms supported by yt-dlp. |
| File Quality | Capped at 720p or low bitrate audio to save bandwidth. | Full 1080p / 4K video extraction and FLAC/MP3 audio. |
| Downtime & Reliability | Frequently banned or throttled by Telegram Bot API limits. | Dedicated access with personalized API quota management. |
Before diving into the setup code, let's explore top Telegram tech and utility groups to stay updated with the latest open-source automation scripts:
To run your self-hosted Telegram bot 24/7, ensure your environment meets the following baseline criteria:
yt-dlp for merging video and audio streams into single containers (MP4/MKV) and audio extraction (MP3).@BotFather to generate your HTTP API token.Every Telegram bot requires a unique API authentication token issued by Telegram's official bot manager.
@BotFather./newbot.bot (e.g., MyMediaVault_Downloader_bot).1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ) and keep it secure..env file.
Log into your Linux VPS terminal via SSH and install system-level packages including ffmpeg and Python build tools:
# Update package indices and install FFmpeg & Python venv sudo apt update && sudo apt install -y python3 python3-pip python3-venv ffmpeg git # Create a project directory mkdir -p ~/telegram-downloader-bot && cd ~/telegram-downloader-bot # Set up a isolated Python virtual environment python3 -m venv venv source venv/bin/activate # Upgrade pip and install core libraries pip install --upgrade pip pip install python-telegram-bot[job-queue] yt-dlp python-dotenv
Create the main bot script named bot.py. This production script features:
import os
import asyncio
import logging
from pathlib import Path
from dotenv import load_dotenv
from telegram import Update
from telegram.ext import (
Application,
CommandHandler,
MessageHandler,
ContextTypes,
filters,
)
import yt_dlp
# Load environment variables
load_dotenv()
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
ALLOWED_USER_IDS = [int(uid.strip()) for uid in os.getenv("ALLOWED_USER_IDS", "").split(",") if uid.strip()]
# Configure Logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
level=logging.INFO,
)
logger = logging.getLogger(__name__)
DOWNLOAD_DIR = Path("./downloads")
DOWNLOAD_DIR.mkdir(exist_ok=True)
def is_authorized(user_id: int) -> bool:
"""Check if the user is authorized to use this bot."""
if not ALLOWED_USER_IDS:
return True # Open to public if no IDs configured
return user_id in ALLOWED_USER_IDS
async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Send welcome message upon /start command."""
user = update.effective_user
if not is_authorized(user.id):
await update.message.reply_text("🚫 Unauthorized access. This is a private self-hosted bot.")
return
welcome_text = (
f"👋 Hello {user.first_name}!
"
"🎬 **Welcome to your Self-Hosted Media Downloader Bot**
"
"Send me any valid video or audio link from YouTube, X/Twitter, Instagram, TikTok, Reddit, or Vimeo, "
"and I will extract and deliver the media directly into this chat!
"
"Commands:
"
"/start - Display welcome message
"
"/help - Usage guidelines & limits"
)
await update.message.reply_markdown(welcome_text)
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Send usage guidelines."""
help_text = (
"💡 **How to Use:**
"
"1. Copy a media URL from your browser or app.
"
"2. Paste the link directly in this chat.
"
"3. Wait a few moments while the bot downloads and processes the file.
"
"⚙️ **Telegram Bot API Limits:**
"
"• Max Telegram Upload: **50MB** (Bots without local API server).
"
"• Files exceeding 50MB will automatically output audio format."
)
await update.message.reply_markdown(help_text)
def extract_media_info(url: str, download_path: Path):
"""Execute yt-dlp extraction synchronously inside worker thread."""
ydl_opts = {
'format': 'bestvideo[ext=mp4][vcodec^=avc1]+bestaudio[ext=m4a]/best[ext=mp4]/best',
'outtmpl': str(download_path / '%(title).50s.%(ext)s'),
'merge_output_format': 'mp4',
'quiet': True,
'no_warnings': True,
'max_filesize': 50 * 1024 * 1024, # 50MB Telegram Bot API limit
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
if not os.path.exists(filename) and os.path.exists(filename.rsplit('.', 1)[0] + '.mp4'):
filename = filename.rsplit('.', 1)[0] + '.mp4'
return info, filename
async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Process incoming URLs and send back media files."""
user_id = update.effective_user.id
if not is_authorized(user_id):
await update.message.reply_text("🚫 Unauthorized user.")
return
url = update.message.text.strip()
if not url.startswith(("http://", "https://")):
await update.message.reply_text("⚠️ Please send a valid URL starting with http:// or https://")
return
status_msg = await update.message.reply_text("⏳ Processing link with yt-dlp...")
try:
loop = asyncio.get_running_loop()
await status_msg.edit_text("📥 Downloading media from source...")
info, file_path = await loop.run_in_executor(
None, extract_media_info, url, DOWNLOAD_DIR
)
if not os.path.exists(file_path):
await status_msg.edit_text("❌ Download failed or file exceeded the 50MB Telegram threshold.")
return
file_size_mb = os.path.getsize(file_path) / (1024 * 1024)
title = info.get('title', 'Media File')
duration = info.get('duration', 0)
await status_msg.edit_text(f"📤 Uploading to Telegram ({file_size_mb:.1f} MB)...")
with open(file_path, 'rb') as video_file:
await update.message.reply_video(
video=video_file,
caption=f"🎥 **{title}**
⏱️ Duration: {duration}s",
parse_mode="Markdown",
supports_streaming=True,
)
await status_msg.delete()
except Exception as e:
logger.error(f"Error handling URL {url}: {e}")
await status_msg.edit_text(f"❌ Error extracting media: {str(e)[:150]}")
finally:
for f in DOWNLOAD_DIR.glob("*"):
try:
if f.is_file():
f.unlink()
except Exception:
pass
def main():
"""Start the Telegram bot."""
if not TELEGRAM_BOT_TOKEN:
raise ValueError("TELEGRAM_BOT_TOKEN environment variable is missing!")
app = Application.builder().token(TELEGRAM_BOT_TOKEN).build()
app.add_handler(CommandHandler("start", start_command))
app.add_handler(CommandHandler("help", help_command))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_url))
logger.info("🚀 Media Downloader Bot is running...")
app.run_polling()
if __name__ == "__main__":
main()
Create a .env file in the same directory to store your credentials securely:
TELEGRAM_BOT_TOKEN=1234567890:ABCdefGhIJKlmNoPQRsTUVwxyZ ALLOWED_USER_IDS=123456789,987654321
(Tip: You can find your numeric Telegram user ID by messaging @userinfobot on Telegram.)
To ensure your downloader bot runs continuously in the background and restarts automatically if your server reboots or crashes, configure a Linux systemd daemon service.
sudo nano /etc/systemd/system/telegram-downloader.service
Paste the following service configuration into the editor (replace ubuntu with your Linux username):
[Unit] Description=Telegram Media Downloader Bot (yt-dlp) After=network.target [Service] Type=simple User=ubuntu WorkingDirectory=/home/ubuntu/telegram-downloader-bot ExecStart=/home/ubuntu/telegram-downloader-bot/venv/bin/python bot.py Restart=always RestartSec=5 Environment=PYTHONUNBUFFERED=1 [Install] WantedBy=multi-user.target
Enable and launch your new service using terminal commands:
# Reload systemd configuration sudo systemctl daemon-reload # Enable service auto-start on reboot sudo systemctl enable telegram-downloader # Start the bot immediately sudo systemctl start telegram-downloader # Check service live status sudo systemctl status telegram-downloader
For containerized infrastructure, you can deploy the bot using Docker and Docker Compose. This eliminates manual dependency management across different host operating systems.
FROM python:3.11-slim # Install system dependencies including FFmpeg RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "bot.py"]
version: '3.8'
services:
telegram-downloader:
build: .
container_name: telegram_media_downloader
restart: unless-stopped
env_file:
- .env
volumes:
- ./downloads:/app/downloads
Launch the container in detached mode with a single command:
docker compose up -d --build
Explore additional high-utility open-source bots and python scripts in our verified Telegram Bot Directory below:
Standard Telegram Bot API limits file uploads via HTTPS POST to 50MB. To download and send files up to 2GB (or 4GB with Telegram Premium), you can run a self-hosted Telegram Bot API Server in local mode on your VPS. Alternatively, your bot can extract audio-only (MP3) or compress video bitrates when files exceed 50MB.
Platforms like YouTube and TikTok frequently update their playback algorithms. To prevent download errors, keep yt-dlp up to date. If running via systemd, add a weekly cron job: 0 3 * * 0 /home/ubuntu/telegram-downloader-bot/venv/bin/pip install --upgrade yt-dlp.
Yes! In the bot.py implementation above, set the ALLOWED_USER_IDS variable in your .env file with your numeric Telegram user ID. Any unauthorized user attempting to paste links will be rejected immediately.
Self-hosting tools like yt-dlp for personal media archiving, fair use, offline playback, and research is generally permissible under local copyright exemptions. However, redistributing copyrighted media publicly or operating commercial scraping services without authorization may violate platform terms of service.
Building your own self-hosted Telegram media downloader bot with Python and yt-dlp guarantees fast, private, and ad-free media downloads directly inside your chat threads. By leveraging systemd or Docker, your bot will run reliably 24/7 with minimal memory overhead.
Ready to discover more powerful Telegram tools and custom bot frameworks? Visit Telekit.link to explore top-rated Telegram bots, developer communities, and automation channels today!
Pick your interests and we'll show you the best communities first.
Stay updated with the latest Telegram groups and channels
Or scan the QR code
Loading community stats...
No active reviews. Be the first to add one!