- Home
- Marketplace
- Video Downloader
Video Downloader
Download video or audio from YouTube and other platforms with yt-dlp, then verify what actually landed on disk.
Use this skill whenever someone asks to download, save, grab, rip, archive or fetch a video, a playlist, a talk, a webinar or the audio from a video, or pastes a video URL and asks for a file — and also when a download needs quality/format selection, subtitles, batch or playlist handling, or has failed and needs diagnosing. Covers the preflight checks that decide whether a download is possible at all (yt-dlp present, ffmpeg present, host reachable from the current network) and requires every reported result to come from real command output — never a described or simulated one.
What it contains
# Video Downloader
Download video or audio from YouTube and other platforms using `yt-dlp`, and verify what actually landed on disk.
The hard part of this task is not the download command — it is knowing whether the download was possible and whether it worked. These are the ways it goes wrong quietly: the host is unreachable from the current environment, `ffmpeg` is missing so a merged download silently yields audio only, a playlist stops at item three, the file lands at 0 bytes, or the platform serves a "video unavailable" page that saves as a valid-looking file. Each step below either produces a real artifact or an error to report.
## Never invent a result
You cannot produce a download by describing one. Do not write progress bars, checkmarks, file sizes, durations, titles, channel names, or a "Saved to ~/Downloads" line unless every one of those values came from a command that ran and returned.
This matters more than it sounds. A user told that a file is at a path where no file exists loses more time than a user told plainly that the download failed — they go looking, find nothing, and no longer know which parts of the report to trust.
Rules that follow from that:
- Every size comes from `ls -lh` or `du -h`. Every duration, resolution or codec comes from `ffprobe`. Every title comes from yt-dlp's own metadata output.
- If the download did not happen, say so and stop. Do not offer a plausible-looking summary of what it would have produced.
- If you are running somewhere without network access to the platform, report that as the outcome — it is a complete and useful answer.
## Step 1 — Preflight
Run these before attempting anything. They take seconds and they determine whether the rest is possible.
```bash
yt-dlp --version # tool present?
ffmpeg -version | head -1 # needed to merge video+audio and to extract audio
```
Install if missing:
```bash
pipx install yt-dlp # or: pip install --break-system-packages yt-dlp
# or: brew install yt-dlp (brings ffmpeg as a dependency)
```
Then confirm the host is actually reachable. Many sandboxes and corporate networks allow package registries but not video platforms:
```bash
curl -sS -D - -o /dev/null --max-time 15 "https://www.youtube.com" 2>&1 | grep -iE "HTTP/|deny"
```
A `403` with `x-deny-reason: host_not_allowed` means an egress proxy is blocking the host. No yt-dlp flag works around that — the correct response is to tell the user the environment cannot reach the platform and give them the command to run on their own machine.
`yt-dlp` also ages badly: platforms change their extractors and older versions break with confusing errors. If a download fails oddly, `yt-dlp -U` (or reinstalling) before deep debugging.
## Step 2 — Probe before downloading
Confirm the URL resolves and see what formats exist. This costs one request and prevents downloading the wrong thing.
```bash
yt-dlp --simulate --print "%(title)s | %(duration_string)s | %(uploader)s" "URL"
yt-dlp --list-formats "URL" # when a specific resolution or codec matters
```
If this step fails, stop here and report the actual error. Common ones are covered under Troubleshooting.
## Step 3 — Download
Pick the recipe that matches the request. Default to a sensible cap rather than the largest available file — 4K is rarely what someone means by "download this video".
**Standard video, capped at 1080p:**
```bash
yt-dlp -f "bv*[height<=1080]+ba/b[height<=1080]" \
--merge-output-format mp4 \
-o "~/Downloads/%(title)s.%(ext)s" \
"URL"
```
**Best available quality:**
```bash
yt-dlp -f "bv*+ba/b" --merge-output-format mp4 -o "~/Downloads/%(title)s.%(ext)s" "URL"
```
**Audio only (podcasts, talks, music):**
```bash
yt-dlp -x --audio-format mp3 --audio-quality 0 -o "~/Downloads/%(title)s.%(ext)s" "URL"
```
**With subtitles burned into the container:**
```bash
yt-dlp -f "bv*+ba/b" --write-subs --sub-langs "en,de" --embed-subs \
--merge-output-format mp4 -o "~/Downloads/%(title)s.%(ext)s" "URL"
```
Use `--write-auto-subs` for machine-generated captions when no human ones exist.
**Playlist, resumable:**
```bash
yt-dlp -f "bv*[height<=1080]+ba/b" \
--download-archive ~/Downloads/archive.txt \
-o "~/Downloads/%(playlist_title)s/%(playlist_index)02d - %(title)s.%(ext)s" \
"PLAYLIST_URL"
```
The archive file records completed items, so re-running skips them. Use this for anything over a handful of videos — playlist downloads get interrupted often.
**Batch from a list:**
```bash
yt-dlp -a urls.txt -f "bv*[height<=1080]+ba/b" -o "~/Downloads/%(title)s.%(ext)s"
```
**Keep metadata alongside the file:**
```bash
yt-dlp --write-thumbnail --write-info-json --embed-metadata -o "~/Downloads/%(title)s.%(ext)s" "URL"
```
Useful additions: `-N 4` (parallel fragments, noticeably faster), `--limit-rate 2M` (be polite on shared connections), `--restrict-filenames` (ASCII-only names, safer for scripting), `-c` (resume a partial download).
For content behind a login that the user has an account for — their own uploads, a course they bought — `--cookies-from-browser firefox` (or `chrome`, `safari`) passes their session through. This is for content their account can already reach; it is not a way past a paywall.
## Step 4 — Verify
Do not report success from yt-dlp's exit code alone. Confirm the file exists and is a real media file:
```bash
ls -lh ~/Downloads/*.mp4 | tail -5
ffprobe -v error -show_entries format=duration,size \
-show_entries stream=codec_type,codec_name,height \
-of default=noprint_wrappers=1 "PATH"
```
Check that the duration roughly matches what the probe step reported, and that a `codec_type=video` stream is present. A file with audio only, when video was requested, means `ffmpeg` was missing at download time — install it and re-run.
Report the real path, the real size, and the real duration. If verification fails, that is the result.
## Rights and terms
Downloading is straightforward for content the user owns, content licensed for reuse, and material covered by fair use or fair dealing. Redistribution is a separate question from download, and platform terms of service often prohibit downloading regardless of copyright status.
Note this once where it is relevant and leave the judgement with the user — they know the provenance of their URL and you do not. Do not interrogate them about it, and do not repeat the warning on every download.
## Troubleshooting
| What you see | What it usually is |
|---|---|
| `HTTP Error 403` on the media fetch, or `x-deny-reason` in headers | Network egress blocks the host. Not fixable from here — hand the user the command. |
| `Sign in to confirm you're not a bot` | Rate-limited or datacenter IP. Try `--cookies-from-browser`, or run from a residential connection. |
| `Requested format is not available` | Format selector too strict. Run `--list-formats` and relax it, or fall back to `-f b`. |
| Output is audio-only when video was requested | `ffmpeg` missing at download time. Install it and re-run. |
| `Unable to extract player response` / extractor errors | `yt-dlp` is out of date. Run `yt-dlp -U`. |
| Playlist stops partway | Re-run the same command with `--download-archive`; completed items are skipped. |
| 0-byte or unplayable file | Platform served an error page. Re-probe the URL; the video may be private, region-locked or removed. |
## Reference
Full option list: `yt-dlp --help`, and the output template placeholders (`%(title)s`, `%(id)s`, `%(upload_date)s`, `%(playlist_index)s`, and others) are documented under `yt-dlp --help` in the OUTPUT TEMPLATE section.

