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
ffmpegon yourPATH(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.
--jobsworkers 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.YoutubeDLinstance 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)
| File | Size | Uploaded | |
|---|---|---|---|
| yt_pdlp-0.0.0.dev3.tar.gz | 43.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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