Skip to content

CLI Usage

Tip

TMDB-based filename tokens (%(tmdb_id), %(original_title), etc.) and poster embedding require a TMDB API key — see TMDB API Key for setup.

Basic Commands

# Show help and available sites
python manual.py -h

# Search and download
python manual.py --site streamingcommunity --search "interstellar"

# Auto-download the first result
python manual.py --site streamingcommunity --search "interstellar" --auto-first

# Select a specific result by index (0-based) instead of the first
python manual.py --site streamingcommunity --search "interstellar" --item 2

# Use a site by its index number
python manual.py --site 0 --search "interstellar"

# Skip TS/CAM releases (StreamingCommunity only)
python manual.py --site streamingcommunity --search "interstellar" --skip-ts

# Disable the log file for this run
python manual.py --site streamingcommunity --search "interstellar" --no-log

Series Selection

Use --season and --episode to skip interactive prompts:

# Specific episode
python manual.py --site streamingcommunity --search "breaking bad" --auto-first --season 1 --episode 3

# Range of episodes
python manual.py --site streamingcommunity --search "breaking bad" --auto-first --season 1 --episode "1-5"

# All episodes of a season
python manual.py --site streamingcommunity --search "breaking bad" --auto-first --season 1 --episode "*"

# All episodes of all seasons
python manual.py --site streamingcommunity --search "breaking bad" --auto-first --season "*"

# Multiple seasons
python manual.py --site streamingcommunity --search "breaking bad" --auto-first --season "1-3"

Year Filter

# Exact year
python manual.py --site streamingcommunity --search "dune" --year 2021

# Year range
python manual.py --site streamingcommunity --search "batman" --year "1990-2015"

Stream Track Overrides

# Video resolution
python manual.py --site streamingcommunity --search "interstellar" -sv 1080

# Audio language
python manual.py --site streamingcommunity --search "interstellar" -sa "eng"

# Subtitles
python manual.py --site streamingcommunity --search "interstellar" -ss "eng"

See Stream Selection Filters for the full -sv/-sa/-ss filter syntax (resolution, codec, bitrate, language, Dolby Vision companion).

Console Behaviour Override

# Keep console open (loop mode)
python manual.py --close-console false

# Close console after download
python manual.py --site streamingcommunity --search "interstellar" --close-console true

Proxy

# Use the configured proxy for everything (default scope)
python manual.py --site streamingcommunity --search "interstellar" --use_proxy

# Proxy only the downloads (Velora), scrape directly
python manual.py --site streamingcommunity --search "interstellar" --use_proxy --proxy-scope down

# Proxy only the scraping, download directly
python manual.py --site streamingcommunity --search "interstellar" --use_proxy --proxy-scope scrap

Show Dependency Paths

python manual.py --dep

Direct Download by URL (--down)

Download a stream directly from its URL, bypassing site search entirely. The stream type is auto-detected (MP4 / HLS / DASH / ISM) or can be forced with --type.

# Simple MP4 / auto-detected stream
python manual.py --down "https://example.com/video.mp4" -o "./Video/clip.mp4"

# HLS with a known decryption key
python manual.py --down "https://example.com/master.m3u8" --type hls \
  --key "<KID>:<KEY>" -o "./Video/movie.mkv"

# DASH with a DRM license server (Widevine)
python manual.py --down "https://example.com/manifest.mpd" --type dash \
  --license-url "https://example.com/wv/license" --drm widevine \
  --headers "Authorization: Bearer <token>" -o "./Video/movie.mkv"

# Grab just a clip: segments 10-50, or the 00:01:00-00:05:00 time range
python manual.py --down "https://example.com/master.m3u8" --type hls \
  --max-segments "10-50" -o "./Video/clip.mkv"
python manual.py --down "https://example.com/master.m3u8" --type hls \
  --max-time "00:01:00-00:05:00" -o "./Video/clip.mkv"

Custom JSON Manifest

--down also accepts a local path or URL pointing at a custom JSON manifest — a plain stream description for sources that don't expose a real HLS/DASH/ISM manifest. It's auto-detected when the target is a .json file/URL containing the "vibravid_manifest" marker, no --type needed.

{
  "vibravid_manifest": true,
  "base_url": "https://cdn.example.com/movie/",
  "duration": 5410.0,
  "tracks": [
    {
      "type": "video", "id": "v1", "codecs": "avc1.640028",
      "width": 1920, "height": 1080, "bitrate": 4500000,
      "init": "init_video.mp4",
      "segments": {"template": "chunk_video_$Number$.m4s", "start": 1, "end": 1352, "duration": 4.0}
    },
    {
      "type": "audio", "id": "a1", "language": "eng", "codecs": "mp4a.40.2",
      "init": "init_audio.mp4",
      "segments": {"list": ["seg0.m4s", "seg1.m4s", "seg2.m4s"]}
    }
  ]
}
python manual.py --down "https://example.com/manifest.json" -o "./Video/movie.mkv"
python manual.py --down "./local_manifest.json" -o "./Video/movie.mkv"

Segment modes for a track's segments field:

Mode Fields Behaviour
list array of URLs, or objects with url/size/duration/range explicit segment list
template template, start, step (or duration), end (or count) DASH-style $Number$ / $Time$ / $RepresentationID$ placeholder expansion
ranges / chunk url + explicit ranges array, or chunk + size to auto-split byte-range segments carved out of a single file

init accepts a URL string, an object (url, range), or inline base64 (data) for the initialization segment. Placeholders support zero-padding, e.g. $Number%05d$; $$ escapes a literal $.

Advanced Options

Flag Effect
--use-curl-cffi Download segments via curl_cffi (browser TLS impersonation) instead of Velora — for sites where individual segments are Cloudflare-protected
--no-vault-cache Bypass the DRM key vault cache; force a fresh CDM license request every run (for dynamic/time-sensitive tokens)
--abc Anonymize printed KID:KEY pairs in the console/log, masking alternating characters with ?
--hls-method AES_128\|NONE Override the HLS segment encryption method, ignoring the manifest's own #EXT-X-KEY tag (or supplying one when it has none). NONE treats every segment as already clear; AES_128 forces AES-128-CBC (pair with --hls-key/--hls-iv)
--hls-key <HEX\|BASE64\|FILE> Raw AES-128 key to use instead of fetching URI= from the manifest's #EXT-X-KEY tag
--hls-iv <HEX> IV to use instead of the manifest's IV=0x... (or the implicit per-segment IV)
--skip-content-check Skip the preflight HEAD content-type check for MP4 direct downloads (--type mp4) — needed for single-use download URLs where a HEAD request consumes the link
--skip-sanitize Use the -o output path verbatim (MP4/HLS/DASH/ISM direct downloads), skipping path sanitization (transliteration of non-ASCII characters)
--no-manifest-info Don't print the parsed manifest/streams table
--binary-update Check FFmpeg/Bento4/Shaka Packager/dovi_tool/MKVToolNix/Velora against AstraeLabs/Binary and re-download whichever is outdated
# Manual AES-128 override, e.g. for a manifest missing its own #EXT-X-KEY tag
python manual.py --down "https://example.com/master.m3u8" --type hls \
  --hls-method AES_128 \
  --hls-key "0011223344556677889900112233445566" \
  --hls-iv "00000000000000000000000000000001" \
  -o "./Video/clip.mkv"

Download Queue (--queue-*)

# Queue instead of downloading now
python manual.py --site streamingcommunity --search "interstellar" --item 0 --queue-add
python manual.py --down "https://example.com/movie.mkv" -o "./Video/movie.mkv" --queue-add

# Inspect / manage the queue
python manual.py --queue-list
python manual.py --queue-remove <ID>
python manual.py --queue-clear

# Process every pending (or interrupted) item in order
python manual.py --queue-run

# A failed item is never retried automatically - re-queue it explicitly
python manual.py --queue-retry <ID>
python manual.py --queue-retry-all

# Optional extra pause between items, on top of DOWNLOAD.delay_after_download
# (which each download already sleeps for on its own before exiting)
python manual.py --queue-run --queue-delay 15

Note

Only invocations that would already complete without any prompt can be queued; anything ambiguous (e.g. --global, or a site search with no --item/--auto-first) is rejected at enqueue time.

Items enqueued together share one auto-generated queue name (e.g. 20260723-152525, shown by --queue-list). Most queue commands accept that name to target just one batch instead of every queue, and a run can be further narrowed to specific item ids:

# Target one specific batch
python manual.py --queue-run 20260723-152525
python manual.py --queue-list 20260723-152525
python manual.py --queue-clear 20260723-152525

# Restrict a run to specific item ids (as shown by --queue-list)
python manual.py --queue-run --queue-ids abc12345,def67890

# Interactively pick which queue to run from a numbered list
python manual.py --queue-select
# Global search
python manual.py --global -s "cars"

# Filter by category
python manual.py --category 1    # Anime
python manual.py --category 2    # Movies & Series
python manual.py --category 3    # Series only
python manual.py --category 4    # Movies only