CodeVetter · Repo Unpack · Extension points
yt-dlp/yt-dlp
yt-dlp is built around registries. New site support = a new `InfoExtractor` subclass ending in `IE` registered by importing it in `_extractors.py`. Post-processors are `PP`-suffixed classes in the `postprocessors` dict. Request handlers are `RH`-suffixed classes auto-registered in `_REQUEST_HANDLERS` with optional preference functions. Third parties plug in via `yt_dlp_plugins` namespace packages (extractor/postprocessor), the documented YouTube PO-token provider framework (PTP/PCP/PCSP suffixes), JS challenge providers (JCP), external downloader FDs, and JS runtime registrations. API hooks (progress/post/close/postprocessor) support library embedding.
- InfoExtractor contract: subclass `InfoExtractor`, define `_VALID_URL` (regex or list; `False` for embed-only), implement `_real_extract(url)`; optional hooks `_initialize_pre_login`, `_perform_login` (gated on `_NETRC_MACHINE`), `_real_initialize`, `_GEO_COUNTRIES`/`_GEO_IP_BLOCKS`, `_TESTS`.
- Built-in extractor registration is manual: add an import to `yt_dlp/extractor/_extractors.py`; `extractors.py` then populates the global `extractors` Indirect dict where iteration order determines match precedence.
- Plugin extractors/post-processors: any `yt_dlp_plugins.extractor`/`yt_dlp_plugins.postprocessor` module exposing a public class ending in `IE`/`PP` is discovered via the `PluginFinder` meta-path finder and prepended into the core registries.
- New request handlers: subclass `RequestHandler` (name must end in 'RH'), implement `validate`/`_send`; module-level `_REQUEST_HANDLERS` registration asserts unique `RH_KEY`, and `@register_preference` adds per-request ordering functions.
- YouTube PO-token provider framework: `PoTokenProvider` (suffix 'PTP') with `@register_provider`/`@register_preference`, plus cache providers 'PCP'/'PCSP' — a documented plugin-facing API in `pot/README.md`.
- JS challenge providers: `JsChallengeProvider` (suffix 'JCP') under `extractor/youtube/jsc`, with a builtin quickjs provider — the extension point for pluggable signature/n challenge solvers.
- External downloaders: `ExternalFD` subclasses (`CurlFD`, `AxelFD`, `WgetFD`, `Aria2cFD`, `HttpieFD`, `FFmpegFD`) declare `SUPPORTED_PROTOCOLS`/`SUPPORTED_FEATURES` and are selectable via `--downloader`; `list_external_downloaders` enumerates them for CLI help.
- New download protocols plug into `PROTOCOL_MAP` in `downloader/__init__.py`; `get_suitable_downloader` resolves protocol strings (including '+'-joined multi-format protocols) to FD classes.
- JS runtimes are a named registry: `supported_js_runtimes` maps names to `JsRuntime` subclasses (deno/node/bun/quickjs registered in `__init__.py`), each probing executable versions with `MIN_SUPPORTED_VERSION`.
- Embedding hooks for library use: `add_progress_hook`, `add_post_hook`, `add_close_hook`, `add_postprocessor_hook`, plus `add_post_processor(pp, when=...)` for custom PP stages — the documented surface for API consumers.
- Extractor helpers for result shaping: `url_result`, `playlist_result`, `playlist_from_matches`, `url_transparent` results let an IE delegate to another IE without downloading — the composition mechanism between extractors.