Skip to main content

Grabinator

License: MIT Python 3.10+ Platforms

A command-line downloader for TikTok, YouTube, Dailymotion, SoundCloud, Instagram, X, and Threads — security-hardened, with automatic quality-aware deduplication and playback fixes for native macOS players. Also converts local video files to MP3 with --convert, no network access required.

Table of contents

Features

Sources TikTok, YouTube, Dailymotion, SoundCloud, Instagram, X, Threads
Naming TikTok/Instagram/X/Threads → @username_id.mp4 · YouTube/Dailymotion → title.mp4
Organization Each platform gets its own subfolder (TikTok/, YouTube/, etc.)
Audio --mp3 extracts clean, padding-free audio on any platform
Local conversion --convert PATH turns existing video files into MP3s — no downloading
Captions --captions downloads subtitles only (converted to .srt), for a video or a whole playlist
Channels Point a YouTube channel/handle URL at Grabinator and it downloads every upload, same as a playlist
Playlists Full YouTube/SoundCloud playlist support, with --range to grab a specific span
Quality selection Capped one tier above 1080p by default, or pick interactively with -q
Dedupe Re-downloading never creates duplicates — a lower/equal-quality repeat is skipped, a genuinely better one replaces the old file
macOS fix Auto re-encodes tracks that play in VLC but are silent/blank in QuickTime, Preview, or Photos
Proxy --proxy routes every request (including the connectivity check) through a SOCKS5/HTTP(S) proxy
Cookies --cookies-from-browser or --cookies unlock private/login-required content
Size check -c shows the estimated download size — one total for a whole playlist — before anything downloads

Supported platforms (OS)

Pure Python, using only pathlib/subprocess for filesystem and process work — it runs the same way on:

  • Linux — any distro with Python 3.10+ and ffmpeg available.
  • macOS — including the playback-compatibility fixes this tool specifically adds.
  • Windows — the script forces UTF-8 console output and enables ANSI color processing on startup, so the colored status output and emoji indicators render correctly instead of crashing or printing garbled escape codes on a legacy cmd.exe codepage. Works from PowerShell, Windows Terminal, or plain cmd.exe.

The one external dependency that varies by OS is ffmpeg itself — see Installation for the install command on each.

Installation

git clone https://github.com/eaglesquawk/grabinator.git
cd grabinator
pip install -e .

This also installs yt-dlp, tqdm, and certifi. Separately, install ffmpeg (which includes ffprobe) via your OS package manager:

brew install ffmpeg          # macOS
sudo apt install ffmpeg      # Debian/Ubuntu
winget install ffmpeg        # Windows

Usage

Single items

grabinator "https://www.tiktok.com/@user/video/123"
grabinator "https://www.youtube.com/watch?v=XXXXXXXXXXX"
grabinator "https://www.dailymotion.com/video/XXXXXXX"
grabinator "https://soundcloud.com/artist/track-name"
grabinator "https://www.instagram.com/p/XXXXXXXXXXX/"
grabinator "https://x.com/user/status/XXXXXXXXXXX"
grabinator "https://www.threads.net/@user/post/XXXXXXXXXXX"

Playlists and channels

grabinator "https://www.youtube.com/playlist?list=XXXXXXXXXXX"
grabinator "https://soundcloud.com/artist/sets/album-name"

# A YouTube channel or handle downloads every upload, the same as a playlist —
# no special flag needed, Grabinator recognizes the URL shape automatically
grabinator "https://www.youtube.com/@SomeChannel"
grabinator "https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxxxxxxxx"

# Only videos 3 through 7 of a playlist or channel
grabinator "PLAYLIST_OR_CHANNEL_URL" --range 3-7

# Just the first 10
grabinator "PLAYLIST_OR_CHANNEL_URL" --range 10

Multiple URLs at once

grabinator "URL1,URL2,URL3"

Audio

# Audio only, on any platform — clean MP3, no leading silence
grabinator "URL" --mp3

The leading-silence "padding" that naive MP3 extraction leaves in place comes from source timestamps that don't start at zero — this isn't a TikTok-specific quirk, it affects YouTube (and Dailymotion, SoundCloud, the rest) just as much. --mp3 runs the exact same ffmpeg fix — zeroing negative timestamps and regenerating clean presentation timestamps before encoding — on every platform uniformly, YouTube included, so the output is padding-free no matter where it came from.

# Convert local video files to MP3 instead — no network access at all,
# originals are never touched. PATH can be a file, a folder, or a .txt
# manifest listing one path per line.
grabinator --convert /path/to/videos
grabinator --convert /path/to/video.mp4
grabinator --convert /path/to/list.txt

Captions

# Download only the subtitles for a video, saved as .srt
grabinator "URL" --captions

# Works on a whole playlist or channel too — one .srt per video
grabinator "PLAYLIST_OR_CHANNEL_URL" --captions

# A specific language (default: en)
grabinator "URL" --captions --caption-lang es

Whatever subtitle format the source actually provides gets converted to .srt, so the output is consistent regardless of platform. If a video simply has no captions available, Grabinator says so and moves on rather than failing the whole run.

Quality selection

# Interactively pick a resolution from a numbered menu
grabinator "URL" -q

# See the estimated file size and confirm before downloading
# (one total for an entire playlist, not one prompt per video)
grabinator "URL" -c

Proxy

grabinator "URL" --proxy socks5://127.0.0.1:9050
grabinator "URL" --proxy http://user:pass@host:port

Other flags

grabinator "URL" --silent                  # suppress progress bars and status output
grabinator "URL" --output-dir /some/path   # override the default download folder
grabinator "URL" --log                     # also write this run's output to a timestamped .txt file
grabinator --version                       # print the installed version

--log writes a full copy of everything printed during that run to <output-dir>/logs/grabinator_<timestamp>.txt, one file per run, alongside — not instead of — the normal console output. Live-updating progress-bar frames aren't logged individually (that would just be noise); each bar's final result still is.

Run without installing, straight from the source file:

python src/grabinator/cli.py "URL"

Authentication (cookies)

Some content requires being logged in to view at all — a private Instagram account, an age-restricted YouTube video, some Threads posts. Grabinator doesn't handle logins itself; instead it borrows a session you already have, the same way yt-dlp does under the hood.

# Reuse cookies from a browser you're already logged into
grabinator "PRIVATE_URL" --cookies-from-browser chrome
grabinator "PRIVATE_URL" --cookies-from-browser firefox

# Or use an exported cookies.txt file instead, without touching a live browser profile
grabinator "PRIVATE_URL" --cookies /path/to/cookies.txt

The two are mutually exclusive — pick one. --cookies-from-browser reads directly from that browser's cookie storage each run; --cookies points at a Netscape-format file you've exported once (browser extensions like "Get cookies.txt" can produce this). Neither option is stored, logged, or written anywhere by Grabinator itself — they're passed straight through to yt-dlp for that run only.

Configuration

The default download folder is set at the top of src/grabinator/cli.py:

OUTPUT_DIR = Path.home() / "Downloads" / "media by Grabinator"

Edit that constant, or pass --output-dir on the command line to override it per run. Whatever you choose, each platform still gets its own subfolder underneath it.

Security measures

  • URLs are checked against an explicit host allowlist (TikTok/YouTube/Dailymotion/ SoundCloud/Instagram/X/Threads domains only) before any network request is made.
  • All subprocess calls (ffmpeg, ffprobe) use argument lists, never shell=True.
  • Filenames derived from remote titles/usernames are sanitized, and every final destination path is resolved and verified to stay inside the configured output directory before anything is written — blocking path traversal from a malicious or unexpected title.
  • Per-run URL and playlist-size caps guard against accidental bulk-scraping.
  • The connectivity check only probes the exact host a given URL points to — never a fixed external address unrelated to what you asked to download.
  • --convert never opens the network at all, and never modifies or deletes the original video files it reads.
  • Cookies passed via --cookies-from-browser or --cookies are used only for that run's requests — Grabinator never writes them to disk, logs them, or includes them in the dedupe index.

Testing status

The pure logic (URL/platform detection, path safety, filename sanitization, range parsing, cookie-options handling, etc.) is covered by an automated test suite and verified on every push. A few things are logic-verified but not yet confirmed against real, live usage:

  • Windows. The UTF-8/ANSI console hardening is implemented and tested for correctness, but hasn't been run on an actual Windows machine.
  • Cookies (--cookies-from-browser, --cookies). The options are built and passed to yt-dlp correctly, but haven't been exercised against a real login-gated download.
  • Channel downloads. URL detection and normalization to a channel's "Videos" tab are tested, but a real channel hasn't been downloaded end-to-end yet.
  • Captions. The download and .srt conversion path hasn't been run against a real video with real subtitles.

If you hit something that doesn't work as documented in one of these areas, that's useful to know about.

Built on yt-dlp and ffmpeg. Use it for content you have the right to download — your own uploads, permissively licensed content, or personal archival use consistent with each platform's Terms of Service and applicable copyright law. You're responsible for how you use it.

Development

pip install -e ".[dev]"
pre-commit install
pytest

Linting/formatting runs automatically on commit via pre-commit + ruff. See CONTRIBUTING.md for how to add a new platform, what's expected of a pull request, and the release process. See CHANGELOG.md for the project's history.

Author

EagleSquwak — September 2026

License

MIT

Metadata

Release files for grabinator 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grabinator 0.5.0
File Size Uploaded
grabinator-0.5.0.tar.gz 32.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for grabinator 0.5.0
File Interpreter ABI Platform
grabinator-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 57.7 kB

Release files / grabinator-0.5.0.tar.gz

Download URL grabinator-0.5.0.tar.gz
Size 32.5 kB
Tags Source
SHA-256 checksum
How to use checksums
2ecd07b66a856968e5591c4e0c63fcd1414143a0e7c96c5fe8fb15cf1578674c
BLAKE2b-256 checksum
How to use checksums
be04e2c7f3d67bab12f43fd6fcd0d9984854050ce2c2440839647ccbfb031b39
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release files / grabinator-0.5.0-py3-none-any.whl

Download URL grabinator-0.5.0-py3-none-any.whl
Size 25.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6c796fbde3dc1bbb4f2522314965fac7e86345ba3ec8d38a9f17b17ff25de3eb
BLAKE2b-256 checksum
How to use checksums
215e51657c9e1d65109d7aa1bcce826fd3c2b6f48feb97eeba5907a449328c85
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.0

Release history Release notifications | RSS feed

0.6.0

2 release files

This release

0.5.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page