YouTube channel video/Shorts downloader - CLI and lightweight web UI, with a .txt info file of metrics per video.
Project description
ycdl
A tool to list and download the latest N videos or Shorts from YouTube channels.
It ships both a fast CLI (ycdl) and a lightweight web UI (FastAPI + plain HTML/CSS/JS, no build step). For every downloaded video it writes a .txt info file containing metrics such as views / likes / comments.
[!NOTE] This tool only uses yt-dlp; no API key is required.
Features
- Search by channel URL,
@handleor name - Shorts, regular videos or both (filterable)
- Web UI with a thumbnail grid, multi-select and live progress (SSE)
- Bulk download from the CLI without the UI
- A
<id>-<title>.txtinfo file per video (+ optional.info.json) - Persistent search history (shared by CLI and UI) you can re-run with one click
- Quality selection, audio-only (mp3), concurrent downloads
- MCP server so AI tools (Cursor, Claude, ...) can list/download for you
- Installable via
pip, exposesycdl/ycdownloadcommands
Requirements
- Python 3.10+
- ffmpeg (recommended for merging video+audio and mp3 conversion)
- macOS:
brew install ffmpeg - Ubuntu/Debian:
sudo apt install ffmpeg - Windows: ffmpeg.org
- macOS:
Installation
Clone the repository and install from source:
git clone https://github.com/tolgahanuzun/ycdl.git
cd ycdl
pip install .
For development (editable install with dev tools):
pip install -e ".[dev]"
Not yet published to PyPI; install from source for now.
Quick start
Web UI (recommended)
ycdl serve --open
Opens http://127.0.0.1:8888 in the browser. Enter a channel, list, select and download.
CLI
# List (without downloading)
ycdl list @MrBeast --last 20 --type shorts
# Download the latest 20 Shorts from a channel
ycdl download @MrBeast --last 20 --type shorts -o ./downloads
# Regular videos only, 720p, 4 concurrent
ycdl download @MrBeast -n 10 --type videos -q 720 --concurrency 4
# Download a single video
ycdl download "https://www.youtube.com/watch?v=VIDEO_ID"
# Show the metrics of a single video
ycdl info "https://www.youtube.com/shorts/VIDEO_ID"
python -m ycdl ... works the same way.
CLI commands
| Command | Description |
|---|---|
ycdl list <channel> |
List the channel's latest videos (no download) |
ycdl download <channel|url> |
Download the latest N videos or a single video |
ycdl info <url> |
Show the metrics of a single video |
ycdl history |
Show saved searches (--clear to wipe) |
ycdl serve |
Start the web UI |
ycdl mcp |
Run as an MCP server (for Cursor, Claude, etc.) |
Key options
| Option | Default | Description |
|---|---|---|
--last, -n |
20 |
How many recent videos |
--type, -t |
both |
shorts / videos / both |
--output, -o |
downloads |
Download directory |
--quality, -q |
best |
best / 1080 / 720 / 480 |
--audio-only |
off | Audio only (mp3) |
--concurrency, -c |
3 |
Number of concurrent downloads |
--no-txt |
- | Do not write the .txt info file |
--no-info-json |
- | Do not write .info.json |
Output layout
downloads/
└── <Channel Name>/
├── <id>-<title>.mp4
├── <id>-<title>.txt # views, likes, comments, duration, date, description...
└── <id>-<title>.info.json # compact machine-readable metadata (optional)
Example .txt:
============================================================
Sample Video Title
============================================================
Channel : Test Channel
Video ID : abc123
URL : https://www.youtube.com/watch?v=abc123
Type : Shorts
Upload date : 2026-01-01
Duration : 0:45
--- Metrics ---
Views : 1,234,567
Likes : 8,900
Comments : 120
Environment variables
| Variable | Description |
|---|---|
YCDL_OUTPUT_DIR |
Default download directory |
YCDL_QUALITY |
Default quality |
YCDL_CONCURRENCY |
Default concurrency |
YCDL_HISTORY_FILE |
Search history file (default ~/.ycdl/history.json) |
Development
pip install -e ".[dev]"
ruff check src tests
ruff format src tests
pytest -q
MCP server (Cursor, Claude, etc.)
ycdl can run as an MCP server, so AI tools can list and download videos for you ("download the latest 20 Shorts from @MrBeast").
Install the optional MCP extra (from source) and run it:
pip install -e ".[mcp]"
ycdl mcp # stdio transport
Exposed tools: list_channel, video_info, download, search_history, clear_history.
Connect from Cursor
Add this to your Cursor MCP config (~/.cursor/mcp.json or the project's
.cursor/mcp.json):
{
"mcpServers": {
"ycdl": {
"command": "ycdl",
"args": ["mcp", "--output", "/absolute/path/to/downloads"]
}
}
}
If ycdl is installed in a virtualenv, use that interpreter, e.g.
"command": "/path/to/.venv/bin/ycdl". The same config shape works for other
MCP-compatible clients (Claude Desktop, etc.).
Architecture
core/— yt-dlp wrappers (channel listing, downloading, metadata, job management). Shared by the CLI and the server.cli.py— Typer-based CLI.server/— FastAPI API + static web UI (live progress via SSE).mcp_server.py— MCP server exposing the same core as tools.
Disclaimer
This tool is intended for personal use. You are responsible for respecting copyright and the YouTube Terms of Service for any content you download.
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ycdl-0.1.0.tar.gz.
File metadata
- Download URL: ycdl-0.1.0.tar.gz
- Upload date:
- Size: 25.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c9b4a480ed5f0c76200964f7b1bb11982b3bff9590933e4fb0e3fd98e5ad1c5
|
|
| MD5 |
ceba6f6e0451092756402bed830f6359
|
|
| BLAKE2b-256 |
164c0201b7fe951403701fae41f9afbf662d43067dfbd8531cd65c8f33e79974
|
File details
Details for the file ycdl-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ycdl-0.1.0-py3-none-any.whl
- Upload date:
- Size: 32.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa1e73c57c8a34ac1256d406a5a30281eb3698a4d00f4593a1e2a1ba7605c721
|
|
| MD5 |
e0ac09ee810f787b21b7dcfcde475bf4
|
|
| BLAKE2b-256 |
90c9f94119c3f39dc9fd52d2eaf4af03e4b0a95e2ea4a9775a93f8f913e451ef
|