Skip to main content

your-ytd

A YouTube downloader built on yt-dlp, with two frontends over one core:

  • CLI (ytdl) — interactive prompts or fully scripted flags
  • Web UI (webui/, Reflex) — paste a link, tick playlist items, watch live progress

Features

  • Single videos and playlists (also works with channel /videos URLs)
  • Guided mode: bare ytdl prompts for URL, destination, selection and quality
  • Quality menu with real resolutions and approximate file sizes
    • Best available, per-resolution (up to 4K), or audio-only
  • Playlist selection: download all, or pick items by number/range (1,3,5-8)
  • Destination directory with ~/Downloads fallback, created if missing
  • Live progress (terminal one-liner / web progress bars) and final saved path
  • One failed video never aborts the rest of a playlist

Install

pipx install your-ytd        # recommended — isolated CLI install
# or: pip install your-ytd   # into whatever environment you prefer

Requires Python 3.9+ and pipx (or pip).

ffmpeg is required to merge video+audio streams. Modern YouTube serves most videos as separate streams, so without it you are effectively limited to audio-only downloads:

sudo apt install ffmpeg
# or, without root, a static build:
#   https://johnvansickle.com/ffmpeg/ -> extract into ~/.local/bin

Development setup

git clone https://github.com/manaf-dev/your-ytd
cd your-ytd
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

Usage

ytdl [URL] [-d DEST] [-q QUALITY] [-s SELECTION]
Argument Description
URL YouTube video or playlist URL — prompted for if omitted
-d, --dest Destination directory (default: ~/Downloads) — prompted for if omitted
-q, --quality best, audio, or a max height like 1080 / 720p — skips the quality menu
-s, --select Playlists only: all or items like 1,3,5-8 — skips the selection prompt

Guided mode

Run ytdl with no arguments and it walks you through everything, one prompt at a time — Enter accepts the shown default:

$ ytdl
URL: https://www.youtube.com/playlist?list=...
Destination [/home/you/Downloads]:
Fetching info...
Playlist: My Playlist  (12 videos)
  1) First video [3:21]
  ...
Enter 'a' to download all, or pick items by number/range (e.g. 1,3,5-8). 'q' cancels.
> a

Available qualities:
   1) Best available for each video
   2) Up to 2160p
   ...
Choose quality [1]:

Anything passed as a flag is skipped, so you can guide just one step (ytdl URL still asks for destination/quality). When stdin is not a terminal (scripts, cron), prompts never appear — missing pieces fall back to defaults and a URL becomes a required argument.

How -q resolves:

  • On a single video it picks the exact menu row: 240 matches 240p (mp4, merged), best matches Best available video+audio.
  • On a playlist it picks a cap row: 1080 matches Up to 1080p, and each video gets the best stream at or below that height.
  • Invalid values exit with an error that lists the valid options; the same goes for malformed -s expressions.

Examples

# fully guided prompts
ytdl

# interactive, default destination
ytdl "https://www.youtube.com/watch?v=VIDEO_ID"

# non-interactive: 1080p into a chosen folder
ytdl "https://www.youtube.com/watch?v=VIDEO_ID" -d ~/Videos/youtube -q 1080

# whole playlist, audio only
ytdl "https://www.youtube.com/playlist?list=PLAYLIST_ID" -s all -q audio

# selected episodes at up to 720p
ytdl "https://www.youtube.com/playlist?list=PLAYLIST_ID" -s 1,3,5-8 -q 720

python -m ytdl URL        # same thing without the installed entry point

Interactive flow

Single video:

Me at the zoo

Available qualities:
   1) Best available video+audio
   2) 240p (mp4, merged) ~302.0 KiB
   3) Audio only (m4a) ~302.0 KiB
Choose quality [1]:

Press Enter to accept the default, or type a number.

Playlists first list every entry with durations, then prompt:

Enter 'a' to download all, or pick items by number/range (e.g. 1,3,5-8). 'q' cancels.
> 1,3,5-8      # subset
> a            # everything
> q            # cancel

The quality choice is made once and applied to every selected video; resolution caps adapt automatically to whatever each video offers.

How it works

  1. Probe — the URL is fetched once with playlist entries flattened, so even 500-item playlists list instantly; single videos resolve fully with their format lists.
  2. Select — playlists prompt for all / a subset (ytdl/cli.py reuses the same parser for -s).
  3. Quality — one menu row is chosen and turned into a yt-dlp format selector: exact stream IDs for a single video, height caps for playlists.
  4. Download — each video downloads independently (progress line, then the saved path); one failure never aborts the rest.

Web UI (v2)

Same engine as the CLI, in the browser: thumbnail preview for videos, scrollable playlist checklist with an "All" switch, quality dropdown with sizes, live progress bars per download, and a downloads panel with queued/merging/done/failed states. The destination picker is a server-side folder browser (navigate, jump to Home/Downloads, create subfolders on demand) and the last chosen folder is remembered across restarts.

Setup (once, inside the venv):

pip install -e ".[web]"     # installs Reflex alongside yt-dlp

Run:

cd webui
reflex run

First run compiles the frontend (downloads bun + npm packages — needs a minute or two). Then open http://localhost:3000. The backend API listens on http://localhost:8080 (set via backend_port in webui/rxconfig.py). Downloads run on the machine where the server runs, into the destination you type in step 2.

Project layout

pyproject.toml       # packaging; [web] extra pulls in Reflex
ytdl/                # shared core + CLI
  cli.py             # argument parsing and main flow (one helper per step)
  downloader.py      # yt-dlp wrapper: probe, quality menus, download
  ui.py              # terminal prompts: URL, destination, selection, quality
  __main__.py        # python -m ytdl support
webui/               # Reflex app (v2 frontend)
  rxconfig.py        # theme + plugins
  webui/state.py     # UI state + thread-pool worker feeding progress
  webui/webui.py     # page layout and components

Troubleshooting

  • Downloads suddenly fail / "Unable to extract ..." — YouTube changes constantly and yt-dlp is updated to keep up. Update the package:
    pipx upgrade your-ytd        # or: pip install -U your-ytd
    
  • Only audio offered / merge errors — ffmpeg is missing or not on PATH. Check with ffmpeg -version.
  • Age/region restricted videos fail to probe — not supported in v1; yt-dlp supports cookies if you ever need it (--cookies equivalent).

Notes / known limits

  • Filenames are <title>.<ext>; already-completed files are not re-downloaded.
  • Merged files use mp4 when mp4 streams exist; audio-only keeps its native container (m4a/webm).
  • Very large playlists list quickly because entries are fetched flat, then resolved individually at download time.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

your_ytd-1.0.0.tar.gz (13.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

your_ytd-1.0.0-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file your_ytd-1.0.0.tar.gz.

File metadata

  • Download URL: your_ytd-1.0.0.tar.gz
  • Upload date:
  • Size: 13.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for your_ytd-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bf630ae796291c0ca56198eb31d520b770a00f9be7d15f66d2b0e2a1279f2a05
MD5 6e02c14d8d0fd434a03e8290a97d3c96
BLAKE2b-256 7094d5479bc4ca6a608ee6bff580a20c537f07867d43eb8cc1a4dfab56a17ffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for your_ytd-1.0.0.tar.gz:

Publisher: release.yml on manaf-dev/your-ytd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file your_ytd-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: your_ytd-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 14.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for your_ytd-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6187cbdf5f3431941bf71b14eba66b283b50c877c703e03a3a3d30000330086
MD5 5ecfe6b3d1d33e19b3df015aa5fb773d
BLAKE2b-256 856a0c88b078edfb1af65fb928fb98d1d37c3d2d3fa9335d38930ee90489ac4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for your_ytd-1.0.0-py3-none-any.whl:

Publisher: release.yml on manaf-dev/your-ytd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page