ytdlp.org

Practical yt-dlp docs: install, commands, fixes, cookies, and workflows.

Current section

Developer guide

How to use yt-dlp in Python

yt-dlp is not just a CLI — it is a Python package, and the command-line tool is a thin wrapper around it. If you are writing Python, skip the subprocess gymnastics and import it directly: you get the same downloader, plus structured metadata as plain dicts instead of parsed stdout.

Quick answer

pip install yt-dlp
from yt_dlp import YoutubeDL

with YoutubeDL({"format": "bv*+ba/b"}) as ydl:
    ydl.download(["https://www.youtube.com/watch?v=..."])

That is a complete yt-dlp Python example: best video plus best audio, merged, saved to the current directory. Everything else is configuration on the options dict.

Extract info without downloading

Most integrations want metadata first — title, duration, available formats — before deciding whether to download anything. Pass download=False:

from yt_dlp import YoutubeDL

with YoutubeDL() as ydl:
    info = ydl.extract_info(url, download=False)
    print(info["title"], info["duration"])

The returned dict contains internal objects that will not serialize. If you need to store or return it as JSON, run it through ydl.sanitize_info(info) first — that is what the CLI's -J flag does internally. Full walkthrough in the metadata guide.

The options dict is the CLI flags

Every CLI flag maps to a key in the dict you pass to YoutubeDL. If you know the command line, you already know the library:

opts = {
    "format": "bv*+ba/b",                     # -f
    "outtmpl": "%(uploader)s/%(title)s.%(ext)s",  # -o
    "quiet": True,                             # -q, silence progress output
    "noplaylist": True,                        # --no-playlist, single video only
}

with YoutubeDL(opts) as ydl:
    ydl.download([url])

The authoritative list is the docstring of the YoutubeDL class in the yt-dlp source — it documents every key, and it is more current than any blog post.

Error handling

Downloads fail for reasons outside your control — private videos, geo blocks, extractor breakage, throttling. yt-dlp raises DownloadError for all of them:

from yt_dlp import YoutubeDL
from yt_dlp.utils import DownloadError

try:
    with YoutubeDL({"format": "bv*+ba/b"}) as ydl:
        ydl.download([url])
except DownloadError as e:
    log.warning("import failed for %s: %s", url, e)
    # decide: retry, skip, or surface to the user

yt-dlp retries individual HTTP fragments internally, but job-level retry logic — backoff, dead-letter queues, alerting — belongs in your code. Treat every download as an operation that can fail and your integration will survive the days when an extractor is broken upstream.

Library vs subprocess

Importing the library is the cleanest integration, but shelling out to the CLI is sometimes the more robust choice, and it is worth being honest about when:

  • Version pinning conflicts.yt-dlp needs to be updated constantly; your app's other dependencies may not want to move. A standalone binary updates independently of your virtualenv.
  • Isolation. A crashed or hung download in a subprocess cannot take your worker down with it, and you can kill it with a plain timeout.
  • Non-Python callers. From Node, Go, or Rust, subprocess plus -J output is the only option — see the API guide.

For scripts and single-purpose tools, import the library. For long-running services where a yt-dlp update should not require redeploying your app, subprocess earns its awkwardness.

The mistake to avoid

Do not treat a working yt-dlp embed as done. Extractor code has a shelf life measured in weeks — sites change their players and yt-dlp ships counter-fixes on a rolling basis. The moment you import it, your app inherits that update treadmill, plus YouTube's bot checks when you run from datacenter IPs. Budget for keeping yt-dlp current and for handling "it worked yesterday" failures, or the integration will quietly rot.

Automation

Running this on a schedule? See the API version.

Paste a link and watch one API call do what your batch script does — extraction, retries, and site breakage handled.

Straightforward yt-dlp help for installs, commands, fixes, cookies, and repeatable workflows.

ytdlp.org is an independent, community-maintained documentation site. It is not affiliated with the yt-dlp project — the official source code lives at github.com/yt-dlp/yt-dlp.