├── .github ├── CODEOWNERS └── workflows │ └── build.yml ├── .gitignore ├── Home.md ├── Forks.md ├── Plugins.md ├── Plugin Development.md ├── Extractors.md ├── Installation.md ├── EJS.md ├── PO Token Guide.md └── FAQ.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @yt-dlp/core 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | secrets/ 2 | 3 | 4 | # Text Editor / IDE 5 | .idea 6 | *.iml 7 | .vscode 8 | *.sublime-* 9 | *.code-workspace 10 | -------------------------------------------------------------------------------- /Home.md: -------------------------------------------------------------------------------- 1 | # Welcome to the yt-dlp wiki! 2 | 3 | ### Contributing to the wiki 4 | 5 | If you have any suggestions, open a PR against **https://github.com/yt-dlp/yt-dlp-wiki** 6 | 7 | Do not open issues about the wiki on the main repo 8 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build wiki 2 | on: 3 | push: 4 | branches: 5 | master 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | with: 12 | fetch-depth: 0 13 | ssh-key: ${{ secrets.TOKEN }} 14 | - name: Push to wiki 15 | env: 16 | TOKEN: ${{ secrets.TOKEN }} 17 | if: env.TOKEN != '' 18 | run: | 19 | git remote add upstream git@github.com:yt-dlp/yt-dlp.wiki 20 | git fetch upstream 21 | git push --force upstream master 22 | -------------------------------------------------------------------------------- /Forks.md: -------------------------------------------------------------------------------- 1 | ### Active 2 | 3 | - [youtube-dl](https://github.com/ytdl-org/youtube-dl) - The original project 4 | - [yt-dlp](https://github.com/yt-dlp/yt-dlp) - This project! 5 | - [nicolaasjan/yt-dlp](https://github.com/nicolaasjan/yt-dlp) - Unofficial yt-dlp builds for Windows 7/XP 6 | 7 | ### Inactive 8 | 9 | - [yt-dlc](https://github.com/blackjack4494/yt-dlc)/[youtube-dlc](https://github.com/blackjack4494/youtube-dlc) - [yt-dlp was forked from this](https://github.com/blackjack4494/yt-dlc/issues/289) 10 | - [weeb-dl](https://github.com/animelover1984/youtube-dl) - [Mostly Merged](https://github.com/yt-dlp/yt-dlp/pull/31) into yt-dlp 11 | - [haruhi-dl](https://git.sakamoto.pl/laudom/haruhi-dl) - Partially merged into yt-dlp 12 | 13 | ### Automated releases 14 | 15 | - [yt-dlp nightly](https://github.com/yt-dlp/yt-dlp-nightly-builds) 16 | - [youtube-dl nightly](https://github.com/ytdl-org/ytdl-nightly) 17 | -------------------------------------------------------------------------------- /Plugins.md: -------------------------------------------------------------------------------- 1 | ### [How to use plugins?](https://github.com/yt-dlp/yt-dlp#plugins) 2 | 3 | ### Extractor 4 | 5 | - [YouTube Agegate Bypass](https://github.com/pukkandan/yt-dlp-YTAgeGateBypass) by [pukkandan](https://github.com/pukkandan) 6 | - Bypasses YouTube age-gate using [account proxy](https://youtube-proxy.zerody.one) by [zerodytrash](https://github.com/zerodytrash) 7 | - [YouTube PO Token Framework](https://github.com/coletdjnz/yt-dlp-get-pot) by [coletdjnz](https://github.com/coletdjnz) 8 | - A plugin framework for yt-dlp to support fetching [PO Tokens](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#po-token-guide) from external providers 9 | 10 | ### Postprocessor 11 | 12 | - [Return Youtube Dislikes](https://github.com/pukkandan/yt-dlp-returnyoutubedislike) by [pukkandan](https://github.com/pukkandan) 13 | - Add dislike count from [returnyoutubedislike](https://returnyoutubedislike.com) to Youtube video metadata 14 | - [srt fixer](https://github.com/bindestriche/srt_fix) by [bindestriche](https://github.com/bindestriche) 15 | - Fix [duplicate lines](https://github.com/yt-dlp/yt-dlp/issues/1734) in Youtube's `--auto-subs` when converted to `srt` 16 | - [FixupMtime](https://github.com/bradenhilton/yt-dlp-FixupMtime) by [bradenhilton](https://github.com/bradenhilton) 17 | - Sets the mtime of all files to a given datetime value by key 18 | - [yt-dlp-replaygain](https://github.com/Eboreg/yt-dlp-replaygain) by [Eboreg](https://github.com/Eboreg) 19 | - Applies track and (optionally) album replaygain to downloaded audio playlists or songs 20 | - [yt-dlp-dearrow](https://github.com/QuantumWarpCode/yt-dlp-dearrow) by [QuantumWarpCode](https://github.com/QuantumWarpCode) 21 | - Applies DeArrow community titles to YouTube content 22 | 23 | ### Other 24 | 25 | - [yt-dlp-ChromeCookieUnlock](https://github.com/seproDev/yt-dlp-ChromeCookieUnlock) by [seproDev](https://github.com/seproDev) and [csm10495](https://github.com/csm10495) 26 | - Unlocks the cookie database for chromium based browsers 27 | - [yt-dont-lock-p](https://github.com/Grub4K/yt-dont-lock-p) by [Grub4K](https://github.com/Grub4K) 28 | - Apply a system wake lock during yt-dlp execution 29 | 30 | Extensions that don't use the official plugin system 31 | 32 | - [dl-plus](https://github.com/un-def/dl-plus) by [un-def](https://github.com/un-def) 33 | - A youtube-dl/yt-dlp extension with pluggable extractors 34 | 35 | ### [Check out the yt-dlp-plugins GitHub topic for more](https://github.com/topics/yt-dlp-plugins) 36 | -------------------------------------------------------------------------------- /Plugin Development.md: -------------------------------------------------------------------------------- 1 | # How do I create a plugin for yt-dlp? 2 | A template plugin package repository is available at [yt-dlp/yt-dlp-sample-plugins](https://github.com/yt-dlp/yt-dlp-sample-plugins). 3 | 4 | - To see how to write extractors in general, see the [yt-dlp developer instructions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions). 5 | - For information regarding the plugin spec, see the [plugins section of the yt-dlp README](https://github.com/yt-dlp/yt-dlp#plugins). 6 | 7 | ## Getting Started 8 | 9 | 1. [Create a new repository based on yt-dlp/yt-dlp-sample-plugins](https://github.com/yt-dlp/yt-dlp-sample-plugins/generate) 10 | 2. Check out the source code with: 11 | `git clone git@github.com:YOUR_GITHUB_USERNAME/YOUR_REPOSITORY.git` 12 | 3. [Configure your IDE's run and debug configuration](#Run-and-debug-configuration) (optional) 13 | 4. Write your plugin code in the `yt_dlp_plugins/` folder (where type is either `extractor` or `postprocessor`). See the sample plugins provided and the [yt-dlp developer instructions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions) for more details. 14 | - Some instructions given will not apply to plugin development, but should give you a good idea on what to do. 15 | - The method for testing extractor plugins is the same as with built-in ones. 16 | 5. [Configure your plugin package](#Configuring-your-plugin-package) 17 | 6. [Add](https://git-scm.com/docs/git-add) the new files, [commit](https://git-scm.com/docs/git-commit) them and [push](https://git-scm.com/docs/git-push) the result, like this: 18 | ```git 19 | $ git add yt_dlp_plugins setup.cfg README.md 20 | $ git commit -m 'Add yourplugin plugin' 21 | $ git push origin master 22 | ``` 23 | 24 | --- 25 | 26 | ## Configuring your plugin package 27 | 1. Modify [setup.cfg](https://github.com/yt-dlp/yt-dlp-sample-plugins/blob/master/setup.cfg) with your plugin's name and version. It is recommended to bump the version whenever you make changes or a new release. 28 | 2. Update the installation instructions on [README.md](https://github.com/yt-dlp/yt-dlp-sample-plugins/blob/master/README.md) to point to this repository. 29 | 3. Add `yt-dlp-plugins` to the repository tags for discoverability. 30 | 4. Be sure to remove any of the sample extractors/post-processors. 31 | 32 | ## Run and debug configuration 33 | 1. Set your IDE's run configuration to point to the `yt_dlp` Python module. 34 | 2. Add your project's root directory containing `yt_dlp_plugins` to `PYTHONPATH` environment variable (this may not be necessary with some IDE run configurations). 35 | 3. The `yt_dlp_plugins` folder should be automatically picked up by yt-dlp (run with `-v` to check). 36 | 37 | ## Importing extractors from other plugins 38 | 39 | ```py 40 | from yt_dlp_plugins.extractor.example import ExampleIE 41 | ``` 42 | 43 | This works regardless of where the `example` plugin is installed on the system, as long as yt-dlp can find it. 44 | Your IDE may not be able to resolve the import, but it will work at runtime. 45 | 46 | If the user does not have the `example` plugin installed, the import will fail and your extractor will not be imported (but yt-dlp will continue to run). 47 | 48 | The same applies for any other plugin type. 49 | 50 | ## Poetry configuration 51 | 52 | If you want your plugin to be installable with [poetry](https://python-poetry.org/), you can add the following to your `pyproject.toml`: 53 | 54 | ``` 55 | [tool.poetry] 56 | ... 57 | packages = [{ include = "yt_dlp_plugins" }] 58 | ... 59 | ``` 60 | 61 | See the [Poetry documentation](https://python-poetry.org/docs/pyproject/#packages) for more details. 62 | -------------------------------------------------------------------------------- /Extractors.md: -------------------------------------------------------------------------------- 1 | # YouTube 2 | 3 | > [!IMPORTANT] 4 | > YouTube is gradually enforcing the use of a "PO Token" to be able to download videos. Due to the nature of these tokens, yt-dlp cannot generate them and they must be provided externally. 5 | > 6 | > By default, yt-dlp will attempt to download videos using clients that do not currently require a PO Token. However, some formats and features may not be available without the token(s). 7 | > 8 | > At this time, if you are having issues with the default clients, it is suggested to use the `mweb` client with a PO Token. Refer to the [PO Token Guide](https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide) on how to set up yt-dlp for this. 9 | 10 | ## Exporting YouTube cookies 11 | 12 | > [!CAUTION] 13 | > By using your account with yt-dlp, you run the risk of it being banned (temporarily or permanently). 14 | > Be mindful with the request rate and amount of downloads you make with an account. Use it only when necessary, or consider using a throwaway account. 15 | 16 | > [!NOTE] 17 | > This is only necessary for content that requires an account to access, such as private playlists, age-restricted videos and members-only content. 18 | 19 | If you are unfamiliar with the basics of exporting cookies and passing them to yt-dlp, then first see [How do I pass cookies to yt-dlp?](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp) 20 | 21 | YouTube rotates account cookies frequently on open YouTube browser tabs as a security measure. 22 | To export cookies that will remain working with yt-dlp, you will need to export cookies in such a way that they are never rotated. 23 | 24 | One way to do this is through a private browsing/incognito window: 25 | 1. Open a new private browsing/incognito window and log into YouTube 26 | 2. In same window and same tab from step 1, navigate to `https://www.youtube.com/robots.txt` (this should be the **only** private/incognito browsing tab open) 27 | 3. Export `youtube.com` cookies from the browser, then **close the private browsing/incognito window** so that the session is never opened in the browser again. 28 | 29 | > [!NOTE] 30 | > Do **NOT** use the `--cookies COOKIEFILE --cookies-from-browser BROWSER` method (as described in the above FAQ link) to export your cookies to a cookiefile. This will export **all** of your regular browser cookies, but **not** the cookies from this private/incognito YouTube session. Instead, use one of the browser extensions recommended in the [FAQ](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp). 31 | 32 | 33 | ## Passing Visitor Data without cookies 34 | 35 | In some cases, you may not want to use cookies and instead pass Visitor Data to use in Innertube API requests. 36 | 37 | > [!WARNING] 38 | > This method is **not recommended** for most cases. It requires skipping webpage requests so that the `VISITOR_INFO1_LIVE` cookie does not interfere. This results in more requests needing to be sent as well as less stable extraction. 39 | 40 | You can do this with: 41 | 42 | --extractor-args "youtubetab:skip=webpage" --extractor-args "youtube:player_skip=webpage,configs;visitor_data=VISITOR_DATA_VALUE_HERE" 43 | 44 | ## Common YouTube Errors 45 | 46 | #### `This content isn't available, try again later` 47 | 48 | This error is caused by your YouTube guest session or account exceeding the YouTube video request rate limit. 49 | 50 | It is recommended to add a delay of around 5-10 seconds between downloads with `-t sleep` or [with the sleep options](https://github.com/yt-dlp/yt-dlp#workarounds). 51 | 52 | With the default yt-dlp settings, the rate limit for guest sessions is ~300 videos/hour (~1000 webpage/player requests per hour). For accounts, it is ~2000 videos/hour (~4000 webpage/player requests per hour). 53 | 54 | 55 | ## PO Token Guide 56 | 57 | [This section has been moved to a dedicated page](https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide) 58 | 59 | ## Logging in with OAuth 60 | 61 | > [!CAUTION] 62 | > Due to new restrictions enacted by YouTube, logging in with OAuth no longer works with yt-dlp. [You should use cookies instead.](#exporting-youtube-cookies) 63 | -------------------------------------------------------------------------------- /Installation.md: -------------------------------------------------------------------------------- 1 | You can install yt-dlp either using one of the official releases, or with your favorite package manager 2 | 3 | > If you are unfamiliar with the command line, you may use one of the many third-party GUIs available 4 | 5 | --- 6 | 7 | # Installing the release binary 8 | 9 | You can simply download the [correct binary file](https://github.com/yt-dlp/yt-dlp#release-files) for your OS 10 | 11 | [![Windows](https://img.shields.io/badge/-Windows_x64-blue.svg?style=for-the-badge&logo=windows)](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe) 12 | [![Linux](https://img.shields.io/badge/-Linux/BSD-red.svg?style=for-the-badge&logo=linux)](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp) 13 | [![MacOS](https://img.shields.io/badge/-MacOS-lightblue.svg?style=for-the-badge&logo=apple)](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos) 14 | [![Other variants](https://img.shields.io/badge/-Other-grey.svg?style=for-the-badge)](https://github.com/yt-dlp/yt-dlp#release-files) 15 | 16 | In UNIX-like OSes (MacOS, Linux, BSD), you can also install the application into a location in your `$PATH`, such as `~/.local/bin`, in one of the following ways: 17 | 18 | ```bash 19 | curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o ~/.local/bin/yt-dlp 20 | chmod a+rx ~/.local/bin/yt-dlp # Make executable 21 | ``` 22 | 23 | ```bash 24 | wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O ~/.local/bin/yt-dlp 25 | chmod a+rx ~/.local/bin/yt-dlp # Make executable 26 | ``` 27 | 28 | ```bash 29 | aria2c https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp --dir ~/.local/bin -o yt-dlp 30 | chmod a+rx ~/.local/bin/yt-dlp # Make executable 31 | ``` 32 | 33 | To update, run: 34 | ```bash 35 | yt-dlp -U 36 | ``` 37 | 38 | To use shell completion (autocomplete), look for the completion files in the [source tarball](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.tar.gz). It comes with bash, fish & zsh support. 39 | 40 | # With [pip](https://pypi.org/project/pip) 41 | 42 | You can install the [PyPI package](https://pypi.org/project/yt-dlp) with: 43 | ```bash 44 | python3 -m pip install -U "yt-dlp[default]" 45 | ``` 46 | 47 | You can install without any of the optional dependencies using: 48 | ```bash 49 | python3 -m pip install --no-deps -U yt-dlp 50 | ``` 51 | 52 | 53 | You can also install the nightly version of yt-dlp with: 54 | ```bash 55 | python3 -m pip install -U --pre "yt-dlp[default]" 56 | ``` 57 | 58 | 59 | 60 | If you want to be on the bleeding edge, you can also install the master branch with: 61 | ```bash 62 | python3 -m pip install -U pip hatchling wheel 63 | python3 -m pip install --force-reinstall "yt-dlp[default] @ https://github.com/yt-dlp/yt-dlp/archive/master.tar.gz" 64 | ``` 65 | 66 | On some systems, you may need to use `py` or `python` instead of `python3` 67 | 68 | To update, run: 69 | ```bash 70 | python3 -m pip install -U "yt-dlp[default]" 71 | ``` 72 | 73 | 74 | # Third-party package managers 75 | 76 | **Note**: These packages are maintained by third-parties and may not be up-to-date. Please report any issues to the respective package maintainers 77 | 78 | 79 | Packaging status 80 | 81 | 82 | ## Linux/MacOS 83 | 84 | ### [Homebrew](https://formulae.brew.sh/formula/yt-dlp) 85 | 86 | macOS or Linux users that are using Homebrew can also install it by: 87 | ```bash 88 | brew install yt-dlp 89 | ``` 90 | 91 | To update, run: 92 | ```bash 93 | brew upgrade yt-dlp 94 | ``` 95 | 96 | ### [pacman](https://archlinux.org/packages/extra/any/yt-dlp/) 97 | 98 | Arch Linux users can install it from the official community repository: 99 | ```bash 100 | sudo pacman -Syu yt-dlp 101 | ``` 102 | 103 | pacman will now automatically download the correct dependencies and keep the package up-to-date whenever you update your system with: 104 | ```bash 105 | sudo pacman -Syu 106 | ``` 107 | 108 | ### [APT](https://en.wikipedia.org/wiki/APT_(software)) 109 | 110 | You can download and install yt-dlp for recent Ubuntu and other related Debian-based distributions by adding [this PPA](https://launchpad.net/~tomtomtom/+archive/ubuntu/yt-dlp) 111 | ```bash 112 | sudo add-apt-repository ppa:tomtomtom/yt-dlp # Add ppa repo to apt 113 | sudo apt update # Update package list 114 | sudo apt install yt-dlp # Install yt-dlp 115 | ``` 116 | Your system's package manager will now automatically download the correct dependencies and keep the package updated with the rest of your system whenever you run: 117 | ```bash 118 | sudo apt update 119 | sudo apt install yt-dlp 120 | ``` 121 | 122 | ### [Snap](https://snapcraft.io/yt-dlp) 123 | 124 | You can install yt-dlp on Linux using Snap: 125 | ```bash 126 | sudo snap install --edge yt-dlp 127 | ``` 128 | 129 | To manually update, run: 130 | ```bash 131 | sudo snap refresh --edge yt-dlp 132 | ``` 133 | 134 | ### [MacPorts](https://ports.macports.org/port/yt-dlp/) 135 | 136 | You can install yt-dlp on macOS using MacPorts: 137 | ```bash 138 | sudo port install yt-dlp 139 | ``` 140 | 141 | To update, run: 142 | ```bash 143 | sudo port selfupdate 144 | sudo port upgrade yt-dlp 145 | ``` 146 | 147 | ### [Alpine Linux](https://alpinelinux.org/) 148 | 149 | Make sure you're on the latest version (or edge) - older versions don't receive updates for community repo. 150 | 151 | To install yt-dlp on Alpine Linux: 152 | ```sh 153 | doas apk -U add yt-dlp 154 | ``` 155 | Or alternatively, without any optional dependencies: 156 | ```sh 157 | doas apk -U add yt-dlp-core 158 | ``` 159 | 160 | yt-dlp should upgrade with your system. If you want to do that explicitly: 161 | ```sh 162 | doas apk -U upgrade yt-dlp 163 | ``` 164 | 165 | To uninstall: 166 | ```sh 167 | doas apk del yt-dlp 168 | ``` 169 | 170 | On [postmarketOS](https://postmarketos.org/) you might have to use `sudo` instead of `doas`. 171 | 172 | ## Windows 173 | 174 | ### [Scoop](https://scoop.sh) 175 | 176 | ```powershell 177 | scoop install yt-dlp 178 | ``` 179 | 180 | To update, run: 181 | ```powershell 182 | scoop update yt-dlp 183 | ``` 184 | 185 | ### [Chocolatey](https://community.chocolatey.org/packages/yt-dlp) 186 | 187 | ```powershell 188 | choco install yt-dlp 189 | ``` 190 | 191 | To update, run: 192 | ```powershell 193 | choco upgrade yt-dlp 194 | ``` 195 | 196 | ### [winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/) 197 | 198 | ```powershell 199 | winget install yt-dlp 200 | ``` 201 | 202 | To update, run: 203 | ```powershell 204 | winget upgrade yt-dlp 205 | ``` 206 | 207 | ## Android 208 | 209 | You can use yt-dlp on Android using [Termux](https://termux.dev). Once Termux is installed, open it and run the following commands: 210 | ```bash 211 | termux-setup-storage # Allow termux to download files into your phone's storage 212 | pkg update && pkg upgrade # Update all packages 213 | pkg install python python-pip # Install Python and pip 214 | pip install -U "yt-dlp[default]" # Install yt-dlp with default dependencies 215 | pkg install ffmpeg # OPTIONAL: Install ffmpeg 216 | ``` 217 | 218 | To update, run: 219 | ```bash 220 | pip install -U "yt-dlp[default]" 221 | ``` 222 | -------------------------------------------------------------------------------- /EJS.md: -------------------------------------------------------------------------------- 1 | # External JS Scripts Setup Guide 2 | 3 | To download from YouTube, yt-dlp needs to solve JavaScript challenges presented by YouTube using an external JavaScript runtime. 4 | 5 | This involves running challenge solver scripts maintained at [yt-dlp-ejs](https://github.com/yt-dlp/ejs). Depending on your yt-dlp installation method, you may need to set up and enable these components manually. 6 | 7 | This guide will help you set up and enable the necessary components based on your yt-dlp installation method. 8 | 9 | > [!NOTE] 10 | > EJS replaces the prior JSInterp and PhantomJS based approach. For YouTube both are no longer used. PhantomJS is still being used for a few other extractors, but is planned to be deprecated in the near future. 11 | 12 | ## Setup steps 13 | 14 | 1. [Install a supported JavaScript runtime](#step-1-install-a-supported-javascript-runtime) 15 | 2. [Install EJS challenge solver scripts](#step-2-install-ejs-challenge-solver-scripts) 16 | 17 | ## Step 1: Install a supported JavaScript Runtime 18 | 19 | | JS Runtime | Summary | 20 | |---------------------------------|--------------------------------------| 21 | | [Deno](#deno) (recommended) | Enabled by default. | 22 | | [Node](#node) | Enable with `--js-runtimes node` | 23 | | [Bun](#bun) | Enable with `--js-runtimes bun` | 24 | | [QuickJS](#quickjs--quickjs-ng) | Enable with `--js-runtimes quickjs` | 25 | 26 | 27 | ### deno 28 | 29 | > [!TIP] 30 | > Recommended 31 | 32 | https://deno.com 33 | 34 | #### Installation instructions 35 | 36 | Minimum supported version: `2.0.0` 37 | 38 | Download from https://docs.deno.com/runtime/getting_started/installation/ or from your package manager. 39 | 40 | When grabbing deno manually from the [Github release assets](https://github.com/denoland/deno/releases/latest) you will need to download `deno` and not `denort`. 41 | 42 | #### Enable 43 | 44 | Deno is enabled by default. To supply an optional path, use `--js-runtimes deno:/path/to/deno` 45 | 46 | #### Notes 47 | 48 | - Code is run with restricted permissions (e.g, no file system or network access) 49 | - Supports downloading EJS script dependencies from [npm](https://www.npmjs.com/) (`--remote-components ejs:npm`). 50 | 51 | --- 52 | 53 | ### node 54 | 55 | https://nodejs.org 56 | 57 | #### Installation instructions 58 | 59 | Minimum supported version: `20.0.0` 60 | 61 | Download from https://nodejs.org/en/download/ or from your package manager. 62 | 63 | #### Enable 64 | 65 | Enable with `--js-runtimes node` or `--js-runtimes node:/path/to/node`. 66 | 67 | It is recommended to add this to your [yt-dlp configuration file](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#configuration) to avoid needing to pass it every time. 68 | 69 | #### Notes 70 | 71 | - Runs code with [*some* permissions restricted](https://nodejs.org/api/permissions.html). 72 | 73 | --- 74 | ### bun 75 | 76 | https://bun.com 77 | 78 | #### Installation instructions 79 | 80 | Minimum supported version: `1.0.31` 81 | 82 | Download from https://bun.com/docs/installation or from your package manager. 83 | 84 | #### Enable 85 | 86 | Enable with `--js-runtimes bun` or `--js-runtimes bun:/path/to/bun`. 87 | 88 | It is recommended to add this to your [yt-dlp configuration file](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#configuration) to avoid needing to pass it every time. 89 | 90 | 91 | #### Notes 92 | 93 | - No permission restrictions available. Scripts have full file system and network access. 94 | - Supports downloading EJS script dependencies from [npm](https://www.npmjs.com/) (`--remote-components ejs:npm`). 95 | - No support for SOCKS proxies when downloading EJS script dependencies from npm. 96 | 97 | --- 98 | ### QuickJS / QuickJS-NG 99 | 100 | https://bellard.org/quickjs/ / https://quickjs-ng.github.io/quickjs/ 101 | 102 | #### Installation instructions 103 | 104 | Minimum supported QuickJS version: `2023-12-9` 105 | 106 | All versions of QuickJS-NG are supported. 107 | 108 | Download from https://bellard.org/quickjs/ / https://quickjs-ng.github.io/quickjs/installation or from your package manager. 109 | 110 | #### Enable 111 | 112 | Enable with `--js-runtimes quickjs` or `--js-runtimes quickjs:/path/to/qjs`. 113 | 114 | It is recommended to add this to your [yt-dlp configuration file](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#configuration) to avoid needing to pass it every time. 115 | 116 | 117 | #### Notes 118 | 119 | - QuickJS versions prior to `2025-4-26` are missing optimizations which can lead to execution times of several minutes. 120 | - All QuickJS-NG versions are missing optimizations which can lead to execution times of several minutes. 121 | - Both QuickJS and QuickJS-NG do not fully allow executing files from stdin, so yt-dlp will create temporary files for each EJS script execution. This can theoretically lead to time-of-check to time-of-use (TOCTOU) vulnerabilities. 122 | 123 | 124 | ## Step 2: Install EJS challenge solver scripts 125 | 126 | | yt-dlp distribution | EJS scripts installation options | 127 | |--------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 128 | | Official PyInstaller-bundled executable (e.g. `yt-dlp.exe`, `yt-dlp_macos`, `yt-dlp_linux`, etc) | No additional action required. All the necessary JavaScript components will be bundled with these executables. | 129 | | PyPI package (e.g. installed with pip, pipx, etc): | - [Install and upgrade yt-dlp with `default` dependency group](#option-1-install-the-yt-dlp-ejs-python-package)
- or [enable npm downloads](#option-2-enable-ejs-script-downloads-from-npm) ([deno](#deno)/[bun](#bun) only)
- or [enable GitHub downloads](#option-3-enable-ejs-script-downloads-from-github)
| 130 | | Official zipimport binary (the `yt-dlp` Unix executable) | No additional action required. All the necessary JavaScript components will be bundled with these executables. | 131 | | Third-party package users (e.g. installed with pacman, brew, etc) | The will depend on if your third-party package repository ships or bundles the EJS script package with yt-dlp.

If it does not (or it is out of date):
- [enable npm downloads](#option-2-enable-ejs-script-downloads-from-npm) ([deno](#deno)/[bun](#bun) only)
- or [enable GitHub downloads](#option-3-enable-ejs-script-downloads-from-github)
| 132 | 133 | 134 | ### Option 1: Install the yt-dlp-ejs python package 135 | 136 | yt-dlp ships a companion package, `yt-dlp-ejs`, which contains all the EJS scripts. 137 | 138 | If you installed yt-dlp using the PyPI package (e.g. with pip or pipx), install _and upgrade_ yt-dlp with the `default` dependency group: 139 | 140 | i.e. `pip install -U "yt-dlp[default]"` 141 | 142 | The default dependency group includes the `yt-dlp-ejs` package. 143 | 144 | Refer to https://github.com/yt-dlp/yt-dlp/wiki/Installation#with-pip for more details. 145 | 146 | Alternatively, if you only want to install the EJS package, you can install the `yt-dlp-ejs` package directly from PyPI. The version MUST match the version specified in yt-dlp's `pyproject.toml` for the version of yt-dlp you are using. 147 | 148 | > [!WARNING] 149 | > This library SHOULD be updated alongside yt-dlp to avoid running an outdated version. The version MUST be a supported version as per yt-dlp's pyproject.toml file. yt-dlp may bump the minimum version on updates without warning, and old versions will be ignored by yt-dlp. 150 | 151 | ### Option 2: Enable EJS script downloads from npm 152 | 153 | > [!IMPORTANT] 154 | > This option only works with Deno and Bun runtimes, which support downloading npm packages on-the-fly. 155 | 156 | To enable this, supply `--remote-components ejs:npm` to yt-dlp. It is recommended to add this to your [yt-dlp configuration file](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#configuration) to avoid needing to pass it every time and allow automatic updates. 157 | 158 | ### Option 3: Enable EJS script downloads from GitHub 159 | 160 | yt-dlp can automatically download the EJS scripts directly from GitHub (https://github.com/yt-dlp/ejs). 161 | 162 | To enable this, supply `--remote-components ejs:github` to yt-dlp. It is recommended to add this to your [yt-dlp configuration file](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#configuration) to avoid needing to pass it every time and allow automatic updates. 163 | 164 | 165 | > [!NOTE] 166 | > This method may not work if GitHub and GitHub release assets are not accessible from your network. This includes if you are using yt-dlp with a IPv6 IP-only (e.g., `--force-ipv6`) 167 | 168 | ## Plugins 169 | 170 | You can install alternatives to the built-in JS challenge solvers through plugins. 171 | 172 | ### Featured Plugins: 173 | - [yt-dlp-apple-webkit-jsi](https://github.com/grqz/yt-dlp-apple-webkit-jsi) by [grqz](https://github.com/grqz) 174 | - Experimental Apple WebKit JS Challenge Provider plugin for yt-dlp. Should work on most Apple devices. *Maintained by a yt-dlp maintainer* 175 | 176 | Check out the [yt-dlp-jsc-provider](https://github.com/topics/yt-dlp-jsc-provider) GitHub topic for more JSC Provider plugins. 177 | 178 | For developers, refer to the [JSC Provider developer documentation](https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/youtube/jsc/README.md) 179 | - **Please note: Currently only the base JavaScript Challenge Provider API is public. The API to hook into yt-dlp's EJS scripts is private at this time due to ongoing development with potential breaking changes; it may be made public in the future.** -------------------------------------------------------------------------------- /PO Token Guide.md: -------------------------------------------------------------------------------- 1 | [Go to YouTube Extractor Wiki](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#youtube) 2 | 3 | # YouTube PO Token Guide 4 | 5 | > [!TIP] 6 | > TL;DR recommended setup: Either use a [PO Token Provider plugin](#po-token-provider-plugins), or [manual extraction](#guide-providing-a-po-token-manually-for-use-with-mweb-client), to provide the `mweb` client with a [PO Token for GVS requests](#cases-where-a-po-token-is-required). 7 | > 8 | > See the notice in the [YouTube Extractor Wiki](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#youtube) for more information on the current state of downloading videos from YouTube. 9 | 10 | 11 | 12 | * [YouTube PO Token Guide](#youtube-po-token-guide) 13 | * [Introduction](#introduction) 14 | * [Cases where a PO Token is required](#cases-where-a-po-token-is-required) 15 | * [Current PO Token enforcement](#current-po-token-enforcement) 16 | * [PO Token Provider Plugins](#po-token-provider-plugins) 17 | * [Featured Plugins](#featured-plugins) 18 | * [Guide: Providing a PO Token manually (for use with `mweb` client)](#guide-providing-a-po-token-manually-for-use-with-mweb-client) 19 | * [PO Token for GVS](#po-token-for-gvs) 20 | * [No account](#no-account) 21 | * [With an account](#with-an-account) 22 | * [PO Token for Player or Subs](#po-token-for-player-or-subs) 23 | * [Other PO Token related tools](#other-po-token-related-tools) 24 | * [Technical details](#technical-details) 25 | * [PO Tokens for GVS](#po-tokens-for-gvs) 26 | * [PO Tokens for Player and Subs](#po-tokens-for-player-and-subs) 27 | 28 | 29 | 30 | ## Introduction 31 | 32 | Proof of Origin (PO) Token is a parameter that YouTube requires to be sent with requests from some clients. Without it, requests for the affected clients' format URLs may return HTTP Error 403, or result in your account or IP address being blocked. 33 | 34 | A PO Token is generated by an attestation provider on Web, Android and iOS platforms to attest the requests are coming from a genuine client. 35 | 36 | For yt-dlp, you can provide PO Token(s) using the [`po_token` extractor argument](https://github.com/yt-dlp/yt-dlp#youtube), or you can [install a plugin](#plugins) that hooks into the YouTube extractor to handle fetching a PO Token. 37 | 38 | For more technical details on these tokens, refer to the [technical details section](#technical-details). 39 | 40 | ## Cases where a PO Token is required 41 | 42 | There are currently three cases yt-dlp may require PO Tokens for video downloads, [depending on the client used](#current-po-token-enforcement): 43 | - GVS: Google Video Server requests (video streaming - https, dash, hls, etc.) 44 | - Player: Innertube `player` requests (fetch video format URLs) 45 | - Subs: Subtitle requests 46 | 47 | The PO Tokens may be generated differently for each of these cases, depending on the client. 48 | 49 | ### Current PO Token enforcement 50 | 51 | YouTube is at present rolling out changes to enforce PO Tokens for video playback. Currently, only GVS and Subs require PO Tokens for some clients. 52 | 53 | | Client | PO Token Required For | Notes | 54 | |----------------|-----------------------------|-------------------------------------------------------------------------------------------------| 55 | | `web` | Subs (rolling out), GVS | Only SABR formats available | 56 | | `web_safari` | Subs (rolling out), GVS* | Same as `web`. *Provides HLS (m3u8) formats which do not require PO Token for GVS at this time. | 57 | | `mweb` | GVS | | 58 | | `tv` | Not required | All formats may have DRM if you request too much | 59 | | `tv_simply` | Not required | Account cookies not supported | 60 | | `tv_embedded` | Not required | Requires account cookies | 61 | | `web_embedded` | Not required | Only embeddable videos available | 62 | | `web_music` | GVS | | 63 | | `web_creator` | GVS | Requires account cookies | 64 | | `android` | GVS or Player | Account cookies not supported | 65 | | `android_vr` | Not required | YouTube Kids videos are not available | 66 | | `ios` | GVS or Player (rolling out) | Account cookies not supported | 67 | 68 | For all clients: 69 | - GVS PO Token is not required for YouTube Premium subscribers 70 | - HLS live streams do not require a PO Token (excluding `ios` client) 71 | 72 | You can select what client to use with the [`player_client` extractor argument](https://github.com/yt-dlp/yt-dlp#youtube). 73 | 74 | ## PO Token Provider Plugins 75 | 76 | > [!TIP] 77 | > Recommended 78 | 79 | Manually fetching PO Tokens can be a tedious process. As an alternative, you can install a PO Token Provider plugin to handle fetching PO Tokens automatically. 80 | 81 | ### Featured Plugins 82 | 83 | - [bgutil-ytdlp-pot-provider](https://github.com/Brainicism/bgutil-ytdlp-pot-provider) by [Brainicism](https://github.com/Brainicism) 84 | - A PO Token Provider which uses [BgUtils](https://github.com/LuanRT/BgUtils) to generate PO Tokens. _Not affiliated with yt-dlp._ 85 | 86 | Check out the [yt-dlp-pot-provider GitHub topic](https://github.com/topics/yt-dlp-pot-provider) for more PO Token Provider plugins. 87 | 88 | For developers, refer to the [PO Token Provider developer documentation](https://github.com/yt-dlp/yt-dlp/tree/master/yt_dlp/extractor/youtube/pot/README.md) 89 | 90 | ## Guide: Providing a PO Token manually (for use with `mweb` client) 91 | 92 | This section provides a basic guide on extracting PO Token(s) manually from YouTube in a web browser **for use with the `mweb` client**, and manually passing it to yt-dlp via the [`po_token` extractor argument](https://github.com/yt-dlp/yt-dlp#youtube). 93 | The same PO Token extraction method _may_ work with other web browser-based clients too. 94 | 95 | > [!TIP] 96 | > When supplying multiple PO Tokens, use the same extractor args option and comma-separate the PO Token configurations. For example: 97 | > `--extractor-args "youtube:po_token=mweb.gvs+GVS_PO_TOKEN_VALUE_HERE,mweb.player+PLAYER_PO_TOKEN_VALUE_HERE"` 98 | 99 | 100 | ### PO Token for GVS 101 | 102 | The PO Token used for `web` GVS requests is tied to your YouTube session, so you will need to provide cookies. 103 | 104 | 1. Open **[YouTube Music](https://music.youtube.com)** in a browser. 105 | 2. Open the developer console (F12), then go to the "Network" tab (click the `>>` button if you don't see it) 106 | 3. Filter requests by `v1/player` 107 | 4. Play a video - a `player` request should appear in the network tab 108 | 5. From the most recent `player` request, extract the PO Token from `serviceIntegrityDimensions.poToken` field in the JSON request body 109 | 6. Pass the PO Token for GVS to yt-dlp using `--extractor-args "youtube:player-client=default,mweb;po_token=mweb.gvs+PO_TOKEN_VALUE_HERE"` with cookies (`--cookies COOKIES_FILE` or `--cookies-from-browser`) 110 | 111 | If using an account, [refer to this guide on exporting account cookies](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies) 112 | 113 | (Not recommended) If not using an account, you may also provide visitor data instead of cookies. Refer to [Passing Visitor Data without cookies](https://github.com/yt-dlp/yt-dlp/wiki/Extractors#passing-visitor-data-without-cookies). 114 | 115 | ### PO Token for Player or Subs 116 | 117 | The PO Token for `web`/`mweb` Player or Subs requests is tied to the Video ID. This means you must generate a new PO Token for each video. 118 | 119 | 1. Open **[YouTube Web](https://www.youtube.com)** in a browser. 120 | 2. Open the developer console (F12), then go to the "Network" tab and filter by `v1/player` 121 | 3. Navigate to the video you want to download (e.g. using search - do not go to the video url directly as the page will refresh) 122 | 4. In the request payload JSON, find the PO Token at `serviceIntegrityDimensions.poToken` and save that value 123 | 5. Export cookies from the browser 124 | 125 | **For Subs PO Token:** 126 | - Pass the PO Token for Subs to yt-dlp using `--extractor-args "youtube:po_token=web.subs+PO_TOKEN_VALUE_HERE"` 127 | 128 | **For Player PO Token:** 129 | > [!NOTE] 130 | > If you are using the `web` client and have not disabled the `webpage` request, providing this PO Token is not necessary at this time. 131 | 132 | - Pass the PO Token for Player to yt-dlp using `--extractor-args "youtube:player-client=default,mweb;po_token=mweb.player+PO_TOKEN_VALUE_HERE"` 133 | 134 | 135 | ## Other PO Token related tools 136 | 137 | - [BgUtils](https://github.com/LuanRT/BgUtils) by [LuanRT](https://github.com/LuanRT) 138 | - Utility to generate PoTokens and run BotGuard attestation challenges. 139 | - [YouTube Trusted Session Generator](https://github.com/iv-org/youtube-trusted-session-generator) by [Invidious](https://github.com/iv-org) 140 | - A generator for getting a session that passes all the checks from YouTube side 141 | 142 | ## Technical details 143 | 144 | PO Tokens are still an active area of research, and at the same time YouTube is continuously updating the implementation and enforcement. The following information is based on the current understanding of PO Tokens, and is subject to change. 145 | 146 | A PO Token is generated by either BotGuard (Web), DroidGuard (Android), iOSGuard (iOS). A PO Token from one platform cannot be used on another (i.e., Web PO Token cannot be used on Android or iOS). 147 | 148 | If you are interested, we recommend checking out the [BgUtils](https://github.com/LuanRT/BgUtils) project which does a deeper dive into the BotGuard attestation process. 149 | 150 | ### PO Tokens for GVS 151 | 152 | GVS uses a PO token bound to the user session. 153 | 154 | For Web session tokens: 155 | - When logged out, are bound to a Visitor ID. This Visitor ID is found in the `VISITOR_INFO1_LIVE` cookie, in the `visitorData` value which is sent with Innertube API requests, or with `ytcfg.get('VISITOR_DATA')` in the browser console. 156 | - When logged in, are bound to the account Session ID (first part of the Data Sync ID). This can be found at `responseContext.mainAppWebResponseContext.dataSyncId` in Innertube responses, or with `ytcfg.get('DATASYNC_ID')` in the browser console. 157 | 158 | If a video download fails with an HTTP 403 midway through, then the client likely requires a PO Token for GVS. 159 | 160 | These PO Tokens are only valid for a limited time (usually at least 12 hours), so it will need to be refreshed periodically. However, some reports suggest that the token may be valid for many days. 161 | 162 | ### PO Tokens for Player and Subs 163 | 164 | Web Tokens for player (and subtitles) requests are bound to the video ID the associated `/player` request is for. YouTube has only recently started generating these for some clients (e.g. `web`). 165 | 166 | As of writing, some clients, such as `web_music` use a session-bound PO Token for player requests. This is likely to change. 167 | 168 | For Android (and presumably iOS), the Player PO Token is bound to the user session, similar to GVS tokens. If a Player PO token is provided, the GVS PO token is not required. -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | ### Known issues 2 | 3 | See [this pinned issue](https://github.com/yt-dlp/yt-dlp/issues/3766) for a list of some important currently known issues and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues) for a full list of issues. 4 | 5 | 6 | ### The yt-dlp in my Package Manager is outdated/broken 7 | 8 | Unfortunately, there is nothing we can do if your distribution serves an outdated/broken version. You should report this to the package maintainer or your distribution in their bugtracker or support forum. 9 | 10 | As a last resort, you can also uninstall the version installed by your package manager and follow [our installation instructions](Installation) to install the latest version. 11 | 12 | 13 | ### Do I need any other programs? 14 | 15 | yt-dlp works reasonably well on its own on most sites. However, some sites - most notably YouTube - serve higher quality formats as separate audio and video. You will need [ffmpeg](https://www.ffmpeg.org/) to download and merge such formats. yt-dlp also uses many other optional dependencies for additional features. See [Dependencies](https://github.com/yt-dlp/yt-dlp#dependencies) for more information. 16 | 17 | 18 | ### I extracted a video URL, but it does not play on another machine / in my web browser 19 | 20 | It depends a lot on the service. In many cases, requests for the video (to download/play it) must come from the same IP address and with the same cookies and/or HTTP headers. Use the `--cookies` option to write the required cookies into a file, and advise your downloader to read cookies from that file. Some sites also require a common user agent to be used; manually pass a desired User-Agent to yt-dlp with `--add-headers`. You should also look at any headers/options yt-dlp adds to the download with `--print http_headers`/`--print downloader_options`. Notably, YouTube throttles any request with an http chunk size of > 10MB. 21 | 22 | Please bear in mind that some download protocols are **not** supported by browsers out of the box. If you wish to download such URLs without yt-dlp, your own downloader must support these. 23 | 24 | If you want to play the video on a machine that is not running yt-dlp, you can relay the video content from the machine that runs yt-dlp. You can use `-o -` to let yt-dlp stream a video to stdout, or simply allow the player to download the files written by yt-dlp in turn. 25 | 26 | 27 | ### Video URL contains an ampersand `&` and I'm getting some strange output `[1] 2839` or `'v' is not recognized as an internal or external command` 28 | 29 | That's actually the output from your shell. Since ampersand is one of the special shell characters it's interpreted by the shell preventing you from passing the whole URL to yt-dlp. To disable your shell from interpreting the ampersands (or any other special characters) you have to either put the whole URL in quotes or escape them with a backslash (which approach will work depends on your shell). 30 | 31 | For example if your URL is https://www.youtube.com/watch?t=4&v=BaW_jenozKc you should end up with following command: 32 | 33 | ```yt-dlp "https://www.youtube.com/watch?t=4&v=BaW_jenozKc"``` 34 | 35 | or 36 | 37 | ```yt-dlp https://www.youtube.com/watch?t=4\&v=BaW_jenozKc``` 38 | 39 | Similar quoting is needed for other options that contain special characters or spaces. 40 | 41 | 42 | ### Output template and Windows batch files 43 | 44 | If you are using an output template inside a Windows batch file then you must escape plain percent characters (`%`) by doubling, so that `-o "%(title)s-%(id)s.%(ext)s"` should become `-o "%%(title)s-%%(id)s.%%(ext)s"`. However you should not touch `%`'s that are not plain characters, e.g. environment variables for expansion should stay intact: `-o "C:\%HOMEPATH%\Desktop\%%(title)s.%%(ext)s"` 45 | 46 | 47 | ### File name too long 48 | 49 | Each OS and filesystem has a limit to the length of a filename. If you are getting this error, then the filename you are trying to save has exceeded this limit. To fix this, use [output template](https://github.com/yt-dlp/yt-dlp#output-template) to set a smaller filename. The [Python string formatting operations](https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting) will be helpful here. For example, `%(uploader).30B - %(title).200B.%(ext)s` will shorten the uploader name to 30 bytes and the title to 200 bytes. If you want this for all of your downloads, put the option into your [configuration file](https://github.com/yt-dlp/yt-dlp#configuration). 50 | 51 | 52 | ### Downloading clips and cutting out Sponsor sections is inaccurate 53 | 54 | Video files cannot be cut at exact timestamps without re-encoding. yt-dlp does not re-encode the video by default, even when cutting is required. You can use `--force-keyframes-at-cuts` to force re-encoding; however, this process is slow - there is no way around this. 55 | 56 | 57 | ### HTTP Error 429: Too Many Requests or 402: Payment Required 58 | 59 | These two error codes indicate that the service is blocking your IP address because of overuse. Usually this is a soft block meaning that you can gain access again after solving CAPTCHA. Just open a browser and solve a CAPTCHA the service suggests you and after that [pass cookies](#how-do-i-pass-cookies-to-yt-dlp) to yt-dlp. Note that if your machine has multiple external IPs then you should also pass exactly the same IP you've used for solving CAPTCHA with [`--source-address`](https://github.com/yt-dlp/yt-dlp#network-options). Also you may need to pass a `User-Agent` HTTP header of your browser with [`--user-agent`](https://github.com/yt-dlp/yt-dlp#workarounds). 60 | 61 | If this is not the case (no CAPTCHA suggested to solve by the service) then you can contact the service and ask them to unblock your IP address, or - if you have acquired a whitelisted IP address already - use the [`--proxy` or `--source-address` options](https://github.com/yt-dlp/yt-dlp#network-options) to select another IP address. 62 | 63 | 64 | ### On Windows, how should I set up ffmpeg and yt-dlp? Where should I put the exe files? 65 | 66 | If you put yt-dlp and ffmpeg in the same directory that you're running the command from, it will work, but that's rather cumbersome. 67 | 68 | To make a different directory work - either for ffmpeg, or for yt-dlp, or for both - simply create the directory (say, `C:\Users\\bin`), put all the executables directly in there, and then [set your PATH environment variable](https://www.java.com/en/download/help/path.xml) to include that directory. 69 | 70 | From then on, after restarting your shell, you will be able to access both yt-dlp and ffmpeg (and yt-dlp will be able to find ffmpeg) by simply typing `yt-dlp` or `ffmpeg`, no matter what directory you're in. 71 | 72 | 73 | ### How do I put downloads into a specific folder? 74 | 75 | Use the `-P "path/to/folder"` to specify a path and an `-o` to specify an [output template](https://github.com/yt-dlp/yt-dlp#output-template). If you want this for all of your downloads, put the option into your [configuration file](https://github.com/yt-dlp/yt-dlp#configuration). 76 | 77 | 78 | ### How do I download a video starting with a `-`? 79 | 80 | Either prepend `https://www.youtube.com/watch?v=` or separate the ID from the options with `--`: 81 | 82 | yt-dlp -- -wNyEUrxzFU 83 | yt-dlp "https://www.youtube.com/watch?v=-wNyEUrxzFU" 84 | 85 | 86 | ### How do I pass cookies to yt-dlp? 87 | 88 | Passing cookies to yt-dlp is a good way to workaround login when a particular extractor does not implement it explicitly. Another use case is working around [CAPTCHA](https://en.wikipedia.org/wiki/CAPTCHA) some websites require you to solve in particular cases in order to get access (e.g. YouTube, CloudFlare). 89 | 90 | The easiest way to pass cookies is to let yt-dlp extract it from your browser (say, Chrome) using `--cookies-from-browser chrome`. In Linux, this searches for config in location `~/.config/google-chrome`. In case you install Chrome using Flatpak, the config is located in `~/.var/app/com.google.Chrome`. To pass the cookies from this location use `--cookies-from-browser chrome:~/.var/app/com.google.Chrome/` 91 | 92 | If you wish to manually pass cookies, use the `--cookies` option, for example: `--cookies /path/to/cookies/file.txt`. 93 | 94 | You can export your cookies to a text file without any third-party software by using yt-dlp's `--cookies-from-browser` option in conjunction with the `--cookies` option, for example: `yt-dlp --cookies-from-browser chrome --cookies cookies.txt`. yt-dlp will extract the browser cookies and save them to the filepath specified after `--cookies`. The resulting text file can then be used with the `--cookies` option. Note though that this method exports your browser's cookies for ALL sites (even if you passed a URL to yt-dlp), so take care in not letting this text file fall into the wrong hands. 95 | 96 | You may also use a conforming browser extension for exporting cookies, such as [Get cookies.txt LOCALLY](https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc) for Chrome or [cookies.txt](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/) for Firefox. As with any browser extension, be careful about what you install. If you had previously installed the "Get cookies.txt" (**not** "LOCALLY") Chrome extension, it's recommended to uninstall it immediately; it has been reported as malware and removed from the Chrome Web Store. 97 | 98 | Note that the cookies file must be in Mozilla/Netscape format and the first line of the cookies file must be either `# HTTP Cookie File` or `# Netscape HTTP Cookie File`. Make sure you have correct [newline format](https://en.wikipedia.org/wiki/Newline) in the cookies file and convert newlines if necessary to correspond with your OS, namely `CRLF` (`\r\n`) for Windows and `LF` (`\n`) for Unix and Unix-like systems (Linux, macOS, etc.). `HTTP Error 400: Bad Request` when using `--cookies` is a good sign of invalid newline format. 99 | 100 | ### How do I stream directly to media player? 101 | 102 | You will first need to tell yt-dlp to stream media to stdout with `-o -`, and also tell your media player to read from stdin (it must be capable of this for streaming) and then pipe former to latter. For example, streaming to [VLC](https://www.videolan.org/) can be achieved with: 103 | 104 | yt-dlp -o - "https://www.youtube.com/watch?v=BaW_jenozKcj" | vlc - 105 | 106 | If you have ffmpeg, you may want to use `-o - --downloader ffmpeg -f "bv*+ba/b"` when streaming to stdout to get the best available quality. 107 | 108 | 109 | ### How do I download only new videos from a playlist? 110 | 111 | Use download-archive feature. With this feature you should initially download the complete playlist with `--download-archive /path/to/download/archive/file.txt` that will record identifiers of all the videos in a special file. Each subsequent run with the same `--download-archive` will download only new videos and skip all videos that have been downloaded before. Note that only successful downloads are recorded in the file. 112 | 113 | For example, at first, 114 | 115 | yt-dlp --download-archive archive.txt "https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re" 116 | 117 | will download the complete `PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re` playlist and create a file `archive.txt`. Each subsequent run will only download new videos if any: 118 | 119 | yt-dlp --download-archive archive.txt "https://www.youtube.com/playlist?list=PLwiyx1dc3P2JR9N8gQaQN_BCvlSlap7re" 120 | 121 | 122 | ### How can I detect whether a given URL is supported by yt-dlp? 123 | 124 | For one, have a look at the [list of supported sites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md). Note that it can sometimes happen that the site changes its URL scheme (say, from https://example.com/video/1234567 to https://example.com/v/1234567) and yt-dlp reports an URL of a service in that list as unsupported. In that case, simply report a site-bug. 125 | 126 | It is *not* possible to detect whether a URL is supported or not. That's because yt-dlp contains a generic extractor which matches **all** URLs. You may be tempted to disable the generic extractor, but the generic extractor not only allows users to extract videos from lots of websites that embed a video from another service, but may also be used to extract video from a service that it's hosting itself. Therefore, we don't recommend disabling it. However, if you still wish to, you can disable it using `--ies default,-generic`. 127 | 128 | If you want to find out whether a given URL is supported, simply call yt-dlp with it. If you get no videos back, chances are the URL is either not referring to a video or unsupported. You can find out which by examining the output (if you run yt-dlp on the console) or catching an `UnsupportedError` exception if you run it from a Python program. 129 | 130 | 131 | ### Why do I need to go through that much red tape when filing bugs? 132 | 133 | Despite the extensive [bug reporting instructions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue), many of the issue reports we get are useless, for instance because people used ancient versions, because of simple syntactic errors (not in yt-dlp but in general shell usage), because the problem was already reported multiple times before, because people did not actually read an error message, even if it said "please install ffmpeg", because people did not mention the URL they were trying to download and many more simple, easy-to-avoid problems, many of which were totally unrelated to yt-dlp. So the issue template forces people to go through the red tape to make sure that they actually read the instructions and that they are not wasting our time. 134 | 135 | yt-dlp is an open-source project manned by too few volunteers, so we'd rather spend time fixing bugs where we are certain none of those simple problems apply, and where we can be reasonably confident to be able to reproduce the issue without asking the reporter repeatedly. As such, the output of `yt-dlp -Uv ` is really all that's required to file an issue. The issue template also guides you through some basic steps you can do, such as checking that your version of yt-dlp is current. 136 | 137 | 138 | ### How can I speed up work on my issue? 139 | 140 | (Also known as: Help, my important issue not being solved!) 141 | 142 | The yt-dlp core developer team is quite small. While we do our best to solve as many issues as possible, sometimes that can take quite a while. To speed up your issue, here's what you can do: 143 | 144 | First of all, please do report the issue [at our issue tracker](https://github.com/yt-dlp/yt-dlp/issues?q=). That allows us to coordinate all efforts by users and developers, and serves as a unified point. Bug reports will not be accepted by any other communication channel. 145 | 146 | Please make sure to read the [bug reporting instructions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue). A lot of bug reports lack the necessary information. At the time of writing this, over 25% of all issues have been closed as invalid/duplicates. A lot of developer time is wasted triaging and answering such issues. 147 | 148 | You are always welcome to take matters into your own hands and submit a pull request (or pay somebody else to do so). Make sure to read the [contributing guidelines](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions) when you do. 149 | 150 | 151 | ### Why am I getting an `incorrect codec parameters` error from ffmpeg when downloading or postprocessing? 152 | 153 | The error message may also include: 154 | * `Could not write header for output file #0` 155 | * `Error number -22 occurred` 156 | * `Invalid argument` 157 | 158 | Older versions of ffmpeg only have experimental support for Opus audio in an mp4 or webm container, and will throw this error if `-strict -2` is not passed as an argument. 159 | 160 | The best solution to this problem is to [update ffmpeg](https://github.com/yt-dlp/FFmpeg-Builds). If you cannot or do not want to update, you can add this to your yt-dlp command: 161 | ``` 162 | --postprocessor-args "ffmpeg:-strict -2" 163 | ``` 164 | 165 | 166 | ### I'm getting HTTP Error 403 and the site has an open issue on the tracker that's labeled "Cloudflare-related". What can I do? 167 | 168 | The 403 errors are coming from Cloudflare; their anti-bot fingerprinting is determining that yt-dlp is not a web browser and blocking yt-dlp's requests to the site you are trying to download from. 169 | 170 | There is a workaround for this. It requires cookies from a browser with the same IP address that you will be using with yt-dlp. Follow these steps: 171 | 172 | 1. Refresh your cookies in browser by navigating to the site you are trying to download from. If you have not done this within the past 30 minutes, you will need to do it again 173 | 174 | 2. Find your browser's User-Agent string; you need the *entire* string (starting with `Mozilla/5.0`) and it needs to be up-to-date (i.e. if your browser updates, you'll need to get its new UA string with the current version) 175 | - the simplest way is to type "my user-agent" into duckduckgo, google, etc. 176 | - for Firefox browsers, you can find the user-agent by navigating to `about:support` 177 | - for Chromium-based browsers, you can find it in `chrome://version` (or your vendor prefix like `brave://version`, etc) 178 | 179 | 3. Pass your browser's user-agent to yt-dlp with `--user-agent "USERAGENT"` along with `--cookies-from-browser firefox` 180 | - replace `USERAGENT` with your actual full user-agent string you got from step 2 181 | - replace `firefox` with the browser that you are using to browse the site 182 | - Or, if you'd rather use a cookies file instead of having yt-dlp extract cookies from your browser, you can use the `--cookies` option, e.g. `--cookies cookies.txt`. Note that the cookies need to be exported from a fresh browser session (see step 1) *within the past 30 minutes*. [More info on exporting cookies](#how-do-i-pass-cookies-to-yt-dlp) 183 | 184 | NOTE: This method reportedly works best with Firefox, and some users have reported problems getting it to work with Edge. 185 | 186 | 187 | ### Why is there a rule against websites "primarily used for piracy"? 188 | 189 | The short answer is that supporting piracy sites would in all likelihood result in the project being shut down. 190 | In the past, other similar projects have been shut down due to supporting piracy sites. 191 | The yt-dlp maintainers are of the position that supporting such sites is not worth the risk. 192 | 193 | 194 | ### What does "sites primarily used for piracy" mean? 195 | 196 | There is no clear-cut definition here, as any site that hosts user-generated content can be used for piracy. 197 | However, common grounds for exclusion from yt-dlp are: 198 | - It is difficult to find a single non-pirated video on the site 199 | - The site is being discussed as a safe haven for pirated content in online forums 200 | - The site's operators are completely anonymous or unknown 201 | 202 | Any of these reasons are enough for a site to be excluded from yt-dlp. 203 | This list is not exhaustive. It is up to the discretion of the maintainers as to whether or not a site will be included in yt-dlp. 204 | --------------------------------------------------------------------------------