
Download Video
- 149 installs
- 13 repo stars
- Updated April 16, 2026
- feiskyer/video-skills
Pull source video from URLs or platforms into local folders for editing, transcription, remix pipelines, or agent workflows that need raw media files.
About
Download-video automates retrieving remote video files into your workspace for content production or agent tooling. It reduces manual browser saves, standardizes where assets land, and enables repeatable ingest steps before editing, captioning, or republishing across channels.
- URL and platform fetch
- Local asset staging
- Pipeline-friendly outputs
- Agent-callable download flow
- Prep for edit or transcribe steps
Download Video by the numbers
- 149 all-time installs (skills.sh)
- Ranked #662 of 2,715 Automation & Workflows skills by installs in the Skillselion catalog
- Data as of Jul 24, 2026 (Skillselion catalog sync)
npx skills add https://github.com/feiskyer/video-skills --skill download-videoAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 149 |
|---|---|
| repo stars | ★ 13 |
| Last updated | April 16, 2026 |
| Repository | feiskyer/video-skills ↗ |
What it does
Pull source video from URLs or platforms into local folders for editing, transcription, remix pipelines, or agent workflows that need raw media files.
Files
Download Video
Download videos from YouTube, Bilibili, Twitter/X, TikTok, and 1000+ other sites using yt-dlp.
Step 1: Check prerequisites
which yt-dlp && yt-dlp --version
which ffmpegIf yt-dlp is missing, install it:
# macOS
brew install yt-dlp ffmpeg
# Cross-platform
pip install yt-dlpStep 2: Download
Use the bundled script — it wraps yt-dlp with sensible defaults and clear error messages.
python3 scripts/download.py "VIDEO_URL"Default output: ~/Downloads/Videos/
Common options
python3 scripts/download.py "URL" -f 1080 # Max 1080p
python3 scripts/download.py "URL" -a # Audio only (MP3)
python3 scripts/download.py "URL" -F # List formats
python3 scripts/download.py "URL" --subs # With subtitles
python3 scripts/download.py "URL" -o ~/Desktop # Custom output dir
python3 scripts/download.py "URL" --cookies chrome # Use browser cookiesDirect yt-dlp commands
For cases the script doesn't cover, use yt-dlp directly:
# Download playlist
yt-dlp -P ~/Downloads/Videos "PLAYLIST_URL"
# Custom filename template
yt-dlp -o "%(uploader)s - %(title)s.%(ext)s" "VIDEO_URL"
# Download with subtitles in specific languages
yt-dlp --write-subs --sub-lang zh,en -P ~/Downloads/Videos "VIDEO_URL"Troubleshooting
Most download failures fall into these categories:
| Symptom | Fix |
|---|---|
| "Sign in required" or age-restricted | Add --cookies chrome to use browser session |
| Only low quality available | Update yt-dlp (brew upgrade yt-dlp), then try with --cookies chrome |
| Slow downloads | Try --concurrent-fragments 3 or --downloader aria2c |
| Network errors (behind firewall) | Use --proxy socks5://127.0.0.1:1080 or set ALL_PROXY env var |
For platform-specific details (YouTube PO tokens, Bilibili series, TikTok watermark removal, etc.), see references/platform-tips.md.
Platform-Specific Tips
YouTube
High-Quality Downloads (1080p+)
YouTube restricts high-quality formats for non-authenticated requests. Solutions:
Option 1: Browser Cookies (Recommended)
yt-dlp --cookies-from-browser chrome "VIDEO_URL"Supported browsers: chrome, firefox, safari, edge, opera, brave
Option 2: PO Token Provider
For persistent high-quality access without browser dependency:
# Find yt-dlp's Python path
head -1 $(which yt-dlp)
# Install the plugin
/path/to/python -m pip install bgutil-ytdlp-pot-providerAge-Restricted Content
Requires authentication via cookies:
yt-dlp --cookies-from-browser chrome "VIDEO_URL"Bilibili
Best Quality
# With authentication for high quality
yt-dlp --cookies-from-browser chrome "https://www.bilibili.com/video/BV..."
# Specify quality
yt-dlp -f "bestvideo+bestaudio" "https://www.bilibili.com/video/BV..."Download Entire Series
yt-dlp -P ~/Downloads/Videos "https://www.bilibili.com/video/BV..." --playlist-items 1-10Twitter/X
Usually works without authentication:
yt-dlp "https://twitter.com/user/status/123456789"
yt-dlp "https://x.com/user/status/123456789"For protected tweets, use cookies:
yt-dlp --cookies-from-browser chrome "https://twitter.com/user/status/123456789"TikTok
# Download single video
yt-dlp "https://www.tiktok.com/@user/video/123456789"
# Without watermark (if available)
yt-dlp -f "download_addr-0" "https://www.tiktok.com/@user/video/123456789"Requires authentication for most content:
yt-dlp --cookies-from-browser chrome "https://www.instagram.com/p/ABC123/"
yt-dlp --cookies-from-browser chrome "https://www.instagram.com/reel/ABC123/"Twitch
VODs
yt-dlp "https://www.twitch.tv/videos/123456789"Clips
yt-dlp "https://clips.twitch.tv/ClipName"Vimeo
# Public videos
yt-dlp "https://vimeo.com/123456789"
# Password-protected
yt-dlp --video-password "PASSWORD" "https://vimeo.com/123456789"Common Issues
"Sign in to confirm your age"
yt-dlp --cookies-from-browser chrome "VIDEO_URL""Video is unavailable"
1. Check if video exists in browser 2. Try with cookies 3. Check if region-restricted (use VPN/proxy)
Slow Downloads
# Limit concurrent downloads
yt-dlp --concurrent-fragments 3 "VIDEO_URL"
# Use external downloader
yt-dlp --downloader aria2c "VIDEO_URL"Network Issues (China)
# Use proxy
yt-dlp --proxy socks5://127.0.0.1:1080 "VIDEO_URL"
# Or environment variable
export ALL_PROXY=socks5://127.0.0.1:1080Useful Options Reference
| Option | Description |
|---|---|
-F | List all formats |
-f FORMAT | Select format |
-P DIR | Output directory |
-o TEMPLATE | Output filename template |
-x | Extract audio |
--audio-format mp3 | Convert to MP3 |
--write-subs | Download subtitles |
--sub-lang LANGS | Subtitle languages |
--cookies-from-browser BROWSER | Use browser cookies |
--proxy URL | Use proxy |
--limit-rate RATE | Limit download speed |
#!/usr/bin/env python3
"""
Universal video downloader using yt-dlp.
Supports 1000+ websites including YouTube, Bilibili, Twitter/X, TikTok, and more.
Default output directory: ~/Downloads/Videos/
Requirements:
- yt-dlp: Install via `brew install yt-dlp` (macOS) or `pip install yt-dlp`
Usage:
python3 download.py "VIDEO_URL"
python3 download.py "VIDEO_URL" -o ~/Desktop
python3 download.py "VIDEO_URL" -f 1080
python3 download.py "VIDEO_URL" -a
python3 download.py "VIDEO_URL" -F
"""
import argparse
import subprocess
import sys
from pathlib import Path
DEFAULT_OUTPUT_DIR = "~/Downloads/Videos"
def check_yt_dlp() -> bool:
"""Check if yt-dlp is installed."""
result = subprocess.run(
["which", "yt-dlp"], capture_output=True, text=True
)
return result.returncode == 0
def get_yt_dlp_version() -> str:
"""Get yt-dlp version."""
result = subprocess.run(
["yt-dlp", "--version"], capture_output=True, text=True
)
return result.stdout.strip() if result.returncode == 0 else "unknown"
def download(
url: str,
output_dir: str = DEFAULT_OUTPUT_DIR,
max_height: int = None,
audio_only: bool = False,
list_formats: bool = False,
with_subs: bool = False,
use_cookies: str = None,
) -> int:
"""
Download video from URL using yt-dlp.
Args:
url: Video URL
output_dir: Output directory
max_height: Maximum video height (e.g., 1080, 720)
audio_only: Extract audio only (as MP3)
list_formats: List available formats instead of downloading
with_subs: Download subtitles
use_cookies: Browser to extract cookies from (chrome, firefox, etc.)
Returns:
Exit code (0 for success)
"""
if not check_yt_dlp():
print("Error: yt-dlp is not installed")
print("Install via: brew install yt-dlp # or: pip install yt-dlp")
return 1
print(f"yt-dlp version: {get_yt_dlp_version()}")
cmd = ["yt-dlp"]
# List formats only
if list_formats:
cmd.extend(["-F", url])
return subprocess.run(cmd).returncode
# Output directory
output_path = Path(output_dir).expanduser().resolve()
output_path.mkdir(parents=True, exist_ok=True)
cmd.extend(["-P", str(output_path)])
# Browser cookies for authentication
if use_cookies:
cmd.extend(["--cookies-from-browser", use_cookies])
# Audio only
if audio_only:
cmd.extend(["-x", "--audio-format", "mp3"])
elif max_height:
cmd.extend(["-f", f"bestvideo[height<={max_height}]+bestaudio/best"])
else:
cmd.extend(["-f", "bestvideo+bestaudio/best"])
# Subtitles
if with_subs:
cmd.extend(["--write-subs", "--sub-lang", "zh,en,ja"])
# Progress display
cmd.append("--progress")
# Add URL
cmd.append(url)
print(f"\nCommand: {' '.join(cmd)}\n")
result = subprocess.run(cmd)
if result.returncode == 0:
print(f"\nDownload completed!")
print(f"Location: {output_path}")
else:
print(f"\nDownload failed (exit code: {result.returncode})")
print("\nTroubleshooting tips:")
print(" 1. Update yt-dlp: brew upgrade yt-dlp")
print(" 2. Try with cookies: python3 download.py URL --cookies chrome")
print(" 3. Check formats: python3 download.py URL -F")
return result.returncode
def main():
parser = argparse.ArgumentParser(
description="Download videos from 1000+ websites using yt-dlp",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s "https://youtu.be/VIDEO_ID"
%(prog)s "https://www.bilibili.com/video/BV..." --cookies chrome
%(prog)s "https://twitter.com/user/status/123" -f 720
%(prog)s "VIDEO_URL" -a # Audio only
%(prog)s "VIDEO_URL" -F # List formats
""",
)
parser.add_argument("url", help="Video URL to download")
parser.add_argument(
"-o", "--output",
default=DEFAULT_OUTPUT_DIR,
help=f"Output directory (default: {DEFAULT_OUTPUT_DIR})",
)
parser.add_argument(
"-f", "--format",
type=int,
metavar="HEIGHT",
help="Max video height (e.g., 1080, 720, 480)",
)
parser.add_argument(
"-a", "--audio",
action="store_true",
help="Download audio only (as MP3)",
)
parser.add_argument(
"-F", "--list-formats",
action="store_true",
help="List available formats",
)
parser.add_argument(
"--subs",
action="store_true",
help="Download subtitles (zh, en, ja)",
)
parser.add_argument(
"--cookies",
metavar="BROWSER",
help="Browser to extract cookies from (chrome, firefox, safari, edge)",
)
args = parser.parse_args()
exit_code = download(
url=args.url,
output_dir=args.output,
max_height=args.format,
audio_only=args.audio,
list_formats=args.list_formats,
with_subs=args.subs,
use_cookies=args.cookies,
)
sys.exit(exit_code)
if __name__ == "__main__":
main()