A clean, self-hosted web UI for downloading YouTube videos and audio — powered by yt-dlp and ffmpeg. No accounts, no tracking, no ads.
Made by @JustAyden & @dash1101
- Video formats — MP4, WebM, MKV with resolution selection (1080p, 720p, 480p, …)
- Audio formats — MP3, FLAC, WAV, AAC, Opus with bitrate selection
- Playlist support — download an entire playlist as a numbered ZIP archive
- Zero frontend build step — single
index.html, no npm, no bundler - Cross-platform — bundles
yt-dlp.exe/ffmpeg.exeon Windows; uses system PATH on Linux/macOS
| Tool | Windows | Linux/macOS |
|---|---|---|
| Python 3.10+ | python.org | apt install python3 / brew install python |
| yt-dlp | bundled .exe |
see below |
| ffmpeg | bundled .exe |
apt install ffmpeg / brew install ffmpeg |
Linux/macOS — install yt-dlp:
sudo curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp \
-o /usr/local/bin/yt-dlp && sudo chmod a+rx /usr/local/bin/yt-dlppip install -r requirements.txtWindows:
start.bat
or
python server.py
Linux / macOS:
chmod +x start.sh && ./start.shor
python3 server.pyThen open http://localhost:5000 in your browser.
| Flag | Default | Description |
|---|---|---|
-p, --port |
5000 |
Port to run the server on |
--host |
127.0.0.1 |
Address to bind to |
Examples:
# Default — localhost only (safe for tunnel/proxy setups)
python3 server.py
# Local network access — accessible from other devices on your LAN
python3 server.py --host 0.0.0.0
# Custom port
python3 server.py --port 8080
# Both
python3 server.py --host 0.0.0.0 --port 8080Note: The default bind address is
127.0.0.1(localhost only). If you're running YTDL-UI on a separate machine and want to access it from another device on your network, pass--host 0.0.0.0. If you're running it behind a reverse proxy or Cloudflare tunnel, keep the default.
Place yt-dlp.exe and ffmpeg.exe in the same folder as server.py. The app detects them automatically.
Download links:
- yt-dlp.exe → github.com/yt-dlp/yt-dlp/releases/latest
- ffmpeg.exe → ffmpeg.org/download.html (get a Windows build from gyan.dev or BtbN)
YTDL-UI binds to 127.0.0.1 by default, making it safe to expose via a reverse proxy (Caddy, Nginx) or a Cloudflare Zero Trust tunnel without opening any ports directly. Point your proxy or tunnel at http://127.0.0.1:5000.
See SETUP.md for a full guide on running YTDL-UI behind Caddy on a Debian server with automatic HTTPS.
For a hardened, always-on deployment that runs as an unprivileged user and restarts automatically:
sudo bash install-service.shThis script:
- Creates a dedicated
ytdluisystem user with no login shell - Installs the app to
/opt/ytdlui - Installs and enables the
ytdluisystemd service
Useful commands after install:
journalctl -u ytdlui -f # live logs
systemctl restart ytdlui # restart
systemctl stop ytdlui # stop| Endpoint | Method | Body | Description |
|---|---|---|---|
/ |
GET | — | Serves the web UI |
/api/info |
POST | {url} |
Returns video/playlist metadata |
/api/download |
POST | {url, format, quality} |
Downloads and streams a single file |
/api/download-playlist |
POST | {url, format, quality} |
Downloads playlist, returns ZIP |
/api/clear-tmp |
POST | — | Manually clears the temp directory |
MIT — do whatever you want with it.
