Universal video downloader. Tries yt-dlp first, falls back to CDP-based browser extraction for stubborn sites.
brew install maxgfr/tap/snatch
snatch --helpOr manually:
git clone https://github.com/maxgfr/snatch.git
cd snatch
npm install
chmod +x download.sh
./download.sh --helpsnatch https://youtube.com/watch?v=dQw4w9WgXcQOptions:
-o, --output <name> Output filename (without extension)
-q, --quality <fmt> Quality/format selector (passed to yt-dlp -f)
-c, --cookies <file> Cookies file (Netscape format, passed to yt-dlp & CDP)
-n, --dry-run Extract video URLs without downloading
-d, --verbose Enable verbose/debug output
-h, --help Show this help
-v, --version Show version
# Download in 720p max
snatch -q 'bestvideo[height<=720]+bestaudio' 'https://youtube.com/watch?v=dQw4w9WgXcQ'
# Just list found video URLs without downloading
snatch -n 'https://example.com/video-page'
# Use cookies for authenticated sites
snatch -c cookies.txt 'https://premium-site.com/video'
# Debug mode to see what's happening
snatch -d 'https://stubborn-site.com/video'- yt-dlp - tries direct download first (supports YouTube, Twitch, Twitter, and 1800+ sites)
- CDP fallback - if yt-dlp fails, launches headless Chrome via raw Chrome DevTools Protocol, intercepts network requests to find video URLs (m3u8, mp4, mpd), extracts from player APIs (JWPlayer, Video.js, Plyr, Flowplayer, Clappr, hls.js, dash.js), and auto-clicks consent/play buttons
- Download - downloads the extracted URL via yt-dlp, curl (mp4), or ffmpeg (m3u8/mpd)
A signed stream URL is rarely usable on its own: the CDN checks who asked for it. So the CDP step doesn't just record the URL, it records how the browser fetched it, and replays that:
- Referer / Origin of the frame that made the request — on a streaming
site that is the embed host (
cloudnestra,vidcdn, …), not the page you passed. Sending the page URL is the classic cause of "extraction worked, but the download 403s". - The browser's User-Agent — Cloudflare's
cf_clearanceand many signed tokens are bound to it. - The session cookie jar, exported in Netscape format and handed to
yt-dlp via
--cookies. - The real HTTP status Chrome got, so a URL that already returned 403 in the browser never wins the ranking.
- The manifest itself, read from the response body: this is how snatch
prefers a master playlist over a single variant (so
-qstill works), reports DRM up front, and detects when a signed master's children need the query propagated (--extractor-args generic:variant_query;…).
snatch -n prints all of it: the URLs, a ready-to-paste yt-dlp command with
those headers, and the full JSON plan. Dry-run deliberately keeps the exported
cookie jar on disk (and says where) so that command still works later — delete
it when you're done, it holds live session cookies.
A DRM-protected stream is reported rather than attempted, and if one happens to rank first, snatch falls through to the best clear stream below it instead of giving up.
Some streaming sites (e.g. 123movies) require solving a captcha before serving video. Snatch detects this and tells you to use cookies:
[err] This site requires a captcha
[!!] Export cookies from your browser and use: snatch -c cookies.txt '<URL>'
How to fix it:
- Install a cookie export extension in your browser (e.g. Get cookies.txt LOCALLY)
- Visit the site in your browser, solve the captcha, and start playing the video
- Export cookies to a
cookies.txtfile (Netscape format) - Run snatch with the
-cflag:
snatch -c cookies.txt 'https://example.com/video-page'The cookies provide your authenticated session so snatch can bypass the captcha.
Everything yt-dlp supports (1800+ sites), plus any site that loads video via standard HTML5 players or streaming protocols — even those that try to hide their video URLs.