# System map — yt-dlp/yt-dlp

> Canonical page: https://codevetter.com/unpack/yt-dlp/system-map

# System map — yt-dlp/yt-dlp

Scanned commit c7fb478d21e9e59524befbe23f7801bb267fb880 (2026-09-16). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

yt-dlp is a single-process Python CLI/package. Execution enters through `yt_dlp.main()` (console script or `python -m yt_dlp`), parses optparse options plus config files into a `ydl_opts` params dict, then constructs one `YoutubeDL` orchestrator that owns the extractor table, post-processor lists, cookiejar, cache, and the RequestDirector. The codebase is layered: `extractor/` produces info dicts, `networking/` abstracts HTTP/WebSocket transports, `downloader/` writes bytes to disk per protocol, and `postprocessor/` runs ffmpeg and other mutations. Shared mutable state lives in `globals.py` `Indirect` cells, which is also how plugins merge into the core registries. Build artifacts (zipapp, PyInstaller binaries, lazy_extractors.py) are produced by the Makefile and bundle/devscripts.
- CLI entrypoint chain: the `yt-dlp` console script maps to `yt_dlp:main`; `python -m yt_dlp` runs `__main__.py` which calls `yt_dlp.main()`; `main()` sets `IN_CLI` and calls `_real_main()`. — [pyproject.toml#L143-144](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/pyproject.toml#L143-L144) [yt_dlp/__main__.py](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/__main__.py) [yt_dlp/__init__.py#L1077-1080](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/__init__.py#L1077-L1080)
- `_real_main()` orchestrates the whole run: `setproctitle`, `parse_options`, plugin loading via `plugin_dirs`/`_load_all_plugins`, `Updater` self-update, then `ydl.download(all_urls)` or `download_with_info_file`, returning `_download_retcode`. — [yt_dlp/__init__.py#L964-1074](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/__init__.py#L964-L1074)
- `YoutubeDL` (4554-line god object) is the central runtime boundary: its `params` dict is the configuration, and it owns `_ies` extractor instances, `_pps` post-processor lists keyed by POSTPROCESS_WHEN, the cookiejar, `Cache`, and the request director. — [yt_dlp/YoutubeDL.py#L204](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/YoutubeDL.py#L204) [yt_dlp/YoutubeDL.py#L634-660](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/YoutubeDL.py#L634-L660) [yt_dlp/utils/_utils.py#L2863](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/utils/_utils.py#L2863)
- The extractor registry is `yt_dlp/extractor/_extractors.py` importing ~1752 IE classes; `extractor/extractors.py` prefers a generated `lazy_extractors.py` (`_CLASS_LOOKUP`) and otherwise eagerly builds the lookup, ordering YouTube extractors first for match performance and `GenericIE` last as the catch-all. — [yt_dlp/extractor/_extractors.py](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/extractor/_extractors.py) [yt_dlp/extractor/extractors.py#L7-31](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/extractor/extractors.py#L7-L31) [devscripts/make_lazy_extractors.py](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/devscripts/make_lazy_extractors.py)
- All HTTP/WebSocket traffic goes through `RequestDirector.send()`, which preference-sorts registered `RequestHandler` subclasses in the module-level `_REQUEST_HANDLERS` dict (Urllib always; Requests, Websockets, CurlCffi imported defensively). — [yt_dlp/networking/common.py#L51-140](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/networking/common.py#L51-L140) [yt_dlp/networking/__init__.py#L19-38](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/networking/__init__.py#L19-L38)
- Downloads are dispatched by protocol: `get_suitable_downloader`/`_get_suitable_downloader` consult `PROTOCOL_MAP` (HlsFD, DashSegmentsFD, F4mFD, RtmpFD, HttpFD, YoutubeLiveChatFD, etc.) and can delegate to external tools (aria2c, wget, curl, axel, httpie, ffmpeg) via `ExternalFD` subclasses. — [yt_dlp/downloader/__init__.py#L4-58](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/downloader/__init__.py#L4-L58) [yt_dlp/downloader/external.py#L37-38](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/downloader/external.py#L37-L38)
- Post-processors register into the `postprocessors` Indirect dict (all classes ending in 'PP'); FFmpeg work is executed by `real_run_ffmpeg` building an argv and calling `Popen.run`. — [yt_dlp/postprocessor/__init__.py#L55-67](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/postprocessor/__init__.py#L55-L67) [yt_dlp/postprocessor/ffmpeg.py#L326-364](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/postprocessor/ffmpeg.py#L326-L364)
- Cross-module shared state is held in `Indirect` cells in `globals.py`: `extractors`, `postprocessors`, `plugin_dirs` (default `['default']`), `plugin_ies`, `plugin_pps`, `supported_js_runtimes`, `supported_remote_components`, `IN_CLI`, `LAZY_EXTRACTORS`. — [yt_dlp/globals.py#L10-41](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/globals.py#L10-L41)
- The package has zero hard dependencies (`dependencies = []`); extras `default`, `curl-cffi`, `secretstorage`, `deno` add requests/urllib3/websockets/brotli/mutagen/pycryptodomex/certifi/yt-dlp-ejs, with exact-pinned `pin-*` groups for reproducible builds. — [pyproject.toml#L46-101](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/pyproject.toml#L46-L101)
- On-disk state: `Cache` writes JSON envelopes (`yt-dlp_version` + data) under `cachedir` (default `$XDG_CACHE_HOME` or `~/.cache/yt-dlp`) keyed by section/key; the download archive is a text file of `extractor_key video_id` lines appended under `locked_file`. — [yt_dlp/cache.py#L17-46](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/cache.py#L17-L46) [yt_dlp/YoutubeDL.py#L3855-3894](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/YoutubeDL.py#L3855-L3894)
- Self-update subsystem `Updater` targets three GitHub repos (stable/nightly/master), downloads the `_update_spec` and `SHA2-256SUMS` release assets, sha256-verifies the new binary, swaps `.new`/`.old` files, and re-executes via `Popen` in `restart()`. — [yt_dlp/update.py#L38-53](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/update.py#L38-L53) [yt_dlp/update.py#L368-500](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/update.py#L368-L500) [yt_dlp/update.py#L502-610](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/update.py#L502-L610)
- Python >=3.10 is enforced twice: `requires-python` in pyproject and an `ImportError` raised at import time in `yt_dlp/__init__.py`. — [pyproject.toml#L18](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/pyproject.toml#L18) [yt_dlp/__init__.py#L3-5](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/yt_dlp/__init__.py#L3-L5)
- Distribution shapes: hatchling wheel/sdist, a zipapp `yt-dlp` (shebang prepended to yt-dlp.zip) built by the Makefile, and PyInstaller bundles wired through the `pyinstaller40` hook-dirs entry point and `bundle/pyinstaller.py`. — [Makefile#L106-130](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/Makefile#L106-L130) [pyproject.toml#L146-147](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/pyproject.toml#L146-L147) [bundle/pyinstaller.py](https://github.com/yt-dlp/yt-dlp/blob/c7fb478d21e9e59524befbe23f7801bb267fb880/bundle/pyinstaller.py)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
