Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

yt-pdlp

Download a large YouTube playlist with several yt-dlp workers running concurrently, showing each worker's live progress in a Textual terminal UI. It supports a planning dry-run and a post-run flush report that reconciles how many videos actually landed versus failed.

Why

yt-dlp has no built-in option to download multiple playlist items in parallel — its -N / --concurrent-fragments flag only parallelises fragments within a single video, so playlist items are processed one at a time. Downloading a ~1,000-item playlist (such as Watch Later) therefore crawls. yt-pdlp runs several downloads at once in one process, with a live UI and resumability.

Requirements

  • Python ≥ 3.11
  • ffmpeg on your PATH (needed to remux to mp4)
  • A browser you are signed in to YouTube with (default: Chrome) — Watch Later is private, so cookies are required.

Install & run

This project uses uv:

uv sync                       # create the environment
uv run yt-pdlp --help  # see all options

Usage

yt-pdlp is a command group with a default command, so a bare invocation downloads:

# Download Watch Later with 4 workers (the defaults)
uv run yt-pdlp

# Six workers, a specific playlist, into ./videos
uv run yt-pdlp -j 6 -u "https://www.youtube.com/playlist?list=PLxxxx" -o ./videos

# Plan only — contacts YouTube read-only, downloads nothing
uv run yt-pdlp --dry-run

# Reconcile an existing output directory without downloading
uv run yt-pdlp flush -o ./videos

download options (the default command)

Option Short Default Meaning
--jobs -j 4 Number of concurrent workers.
--url -u Watch Later Playlist (or any yt-dlp-supported) URL.
--output -o ./downloads Output directory (created if absent).
--browser -b chrome Browser to read cookies from.
--format -f None Remux container; an empty string or None disables remux.
--fragments -N 8 concurrent_fragment_downloads per worker (intra-video).
--dry-run off Plan only; download nothing.
--plain auto Disable the Textual UI; emit line-based progress (auto-on when stdout is not a terminal).

flush options

Option Short Default Meaning
--output -o ./downloads Locate and reconcile this output's state directory.
--url -u (optional) Re-flatten this playlist to define the "requested" set instead of using the cached list.

How it works

  • A shared work queue holds every playlist entry. --jobs workers each pull the next entry and download it, so the work load-balances naturally across videos of very different lengths.
  • Each worker owns its own yt_dlp.YoutubeDL instance and reports progress through a UI-agnostic event stream. A Textual front-end renders per-worker panels and an overall counter; a plain front-end prints line-based progress when there is no terminal.
  • A shared download archive records only successful downloads, so re-running the same command skips what is already done and retries what failed.
  • The browser cookie store is read once and written to a reusable cookie file; every worker then reads the file (browsers lock their cookie database, so reading it from many workers at once would contend).

State directory

Everything lives under <output>/.ytdlp-state/:

File Purpose
cookies.txt Cookies exported once from the browser. Sensitive — it holds a live session; keep it private.
entries.json The flattened playlist: a list of {id, url, title}.
archive.txt The yt-dlp download archive (resume + skip).
failed.txt Outstanding URLs after a run or flush, one per line — retry with yt-dlp -a failed.txt … or just re-run.
report.txt The last completion report.

Downloaded media files go directly under <output>/.

A note on concurrency

The realistic sweet spot is 4–8 workers. The bottleneck is YouTube's per-account/IP throttling (HTTP 429), not your machine — beyond a handful of workers, total throughput usually drops. yt-pdlp warns when you ask for more than 8 but does not stop you.

Development

uv run pytest -q                       # tests
uv run ruff check src tests            # lint
uv run ruff format --check src tests   # formatting
uv run ty check src                    # type-check

The download engine is deliberately decoupled from the UI, and yt-dlp, the network, and the terminal are faked in tests only so the whole tool runs offline in CI.

Metadata

Release files for yt-pdlp 0.0.0.dev3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for yt-pdlp 0.0.0.dev3
File Size Uploaded
yt_pdlp-0.0.0.dev3.tar.gz 43.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for yt-pdlp 0.0.0.dev3
File Interpreter ABI Platform
yt_pdlp-0.0.0.dev3-py3-none-any.whl Python 3 none any Details

Total release size: 70.1 kB

Release files / yt_pdlp-0.0.0.dev3.tar.gz

Download URL yt_pdlp-0.0.0.dev3.tar.gz
Size 43.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4025820387b2cf748483a17fb4d72cdaf00f636554dbdc2799bc2fecfbc56078
BLAKE2b-256 checksum
How to use checksums
fb917f7bc2eeb54cb58e12d8c8f4e3fe91295160772f7a3da154a42fcec758ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.

Transparency log

Release files / yt_pdlp-0.0.0.dev3-py3-none-any.whl

Download URL yt_pdlp-0.0.0.dev3-py3-none-any.whl
Size 26.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70265796d99de73733b828d6d9fb22d27860269f077dfb896e8b740b4ab3f7bf
BLAKE2b-256 checksum
How to use checksums
7e37f86b34e5c5e27d112a9133088950cf563b9be45856dac984a4414269ffb5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 26, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page