Scope of Application
Priority Coverage (usually works directly)
- Douyin videos:
douyin.com、v.douyin.comand other video links - Douyin image-text notes: Automatic download is not currently supported (anti-scraping restrictions); manual screenshots are required
- Bilibili:
bilibili.com、b23.tvetc. - YouTube:
youtube.com、youtu.be - as well as other websites supported by yt-dlp(there are many)
Podcast platforms
- Xiaoyuzhou (single-episode/program page): In most cases, the audio can be downloaded directly (yt-dlp usually works)
- Other podcast platforms: If a direct audio link can be parsed from the page, it can usually also be downloaded
Compliance notice: only use to download content youhave the right to save(for example, content you uploaded yourself/own the copyright to/have authorization for/is permitted by the platform for offline use). When encountering DRM/encryption or platform restrictions, do not attempt to bypass them.
Quick Start
1) Download video (default)
-
Command:
python scripts/download_media.py "<URL>"
-
Default save directory:
- under the user's home directory
~/Downloads/(no longer self-contained, making daily access easier; see DEC-004) - You can customize the output path via the
--out-dirparameter
- under the user's home directory
2) Download audio only (suitable for podcasts / when you only want MP3)
- Command:
python scripts/download_media.py --audio-only --audio-format mp3 "<URL>"
3) If you encounter 403 / need to log in / risk control interception: retry with cookies
Easier (recommended) — directly read browser cookies:
- If the user has already logged in to the site in a browser (Chrome/Firefox/Safari/Edge), directly specify the browser, no manual export needed:
python scripts/download_media.py --cookies-from-browser chrome "<URL>"- Applicable to: Bilibili 412, YouTube age restrictions, Douyin with login state, etc.
Or manually export cookies.txt (Netscape format):
- Have the user export
cookies.txt, then retry:python scripts/download_media.py --cookies "/path/to/cookies.txt" "<URL>"
--cookiesand--cookies-from-browserare mutually exclusive; choose one. Douyin videos do not require manually passing cookies — the script will automatically use a three-level fallback (see "Platform Differences" below), and the last step is automatically retrying with the local browser's guest cookies (no need to log in to Douyin).
4) Need a proxy (optional)
- For example:
--proxy "socks5://127.0.0.1:7890"
5) Specify download path
- The user can specify the save location in natural language, and the AI should automatically convert it to the
--out-dirparameter - Example:
- User says "download to desktop" →
--out-dir ~/Desktop - User says "save to Videos/bilibili" →
--out-dir "~/Videos/bilibili" - User says "download to this folder" (specifying a path) → use the user-specified absolute path
- User says "download to desktop" →
- Note: Ensure the target directory exists; if it does not exist, it can be created automatically
Platform Differences and Limitations (Important)
-
YouTube / Bilibili:
- Common failure reasons: age restrictions, region restrictions, frequent requests triggering risk control, login required
- Handling: cookies, proxy, or lower concurrency/wait and retry
- Additional YouTube note: if Signature solving failed / JS challenge warning appears, you can enable the challenge-solving component per yt-dlp's EJS guidance (e.g. add
--remote-components ejs:github), or have the user provide cookies
-
Douyin videos (three-level automatic fallback, available since v0.3.0 / enhanced in v0.5.0):
- Douyin
www.douyin.combusiness APIs are all behind thea_bogus/msToken signature wall, and downloading directly with yt-dlp will reportFresh cookies are needed。 - When it's a "Douyin domain + user did not explicitly pass cookies" and yt-dlp fails, automatically remediate in order:
- No-login direct connection(v0.3.0, videos only): short link → SSR share page extracts
video_id→aweme.snssdk.com/aweme/v1/play/to get the 302 CDN direct link → download with referer, no cookies/signature needed. - Browser guest cookie retry(v0.5.0, both audio and video): automatically in order from the local machine's
chrome、safariread one copy ofguest cookie(s_v_web_idand other access cookies,no need to log in to Douyin) rerun yt-dlp, and it can pass the "Fresh cookies are needed" validation.
- No-login direct connection(v0.3.0, videos only): short link → SSR share page extracts
- Boundaries: only public videos; private/friends-only visible, deleted, region-restricted, live streams/live replays, and image-text notes are all not applicable (image-text goes through
download_douyin_note.py). When browser cookie reading fails (e.g. Chrome is running and occupying it/no such browser), automatically switch to the next one; if all fail, echo yt-dlp's original error. - The no-login direct link is valid for about 1-2 hours; just rerun after it expires. Since 2026-08-30, the SSR share page has stopped rendering for cookie-less requests
play_addr(monitoring signal #2 hit, risk control returns a shell page), the current main channel is guest cookies; for the evolution record seereferences/douyin-nocookie-approach.md。
- Douyin
-
Spotify:
- Content on Spotify may have DRM, account permission/subscription restrictions, and "downloading" may violate platform terms.
- This skill does not guarantee that a Spotify link can definitely be downloaded.
- Viable alternatives:
- Use the official offline feature (if the platform provides it)
- Provide that podcast's RSS/audio direct link(if you own/can obtain it), then use this script to download
Bundled scripts
-
scripts/download_media.py- Based on
yt-dlpuniversal downloader - Output: on success, the last line
SAVED_FILEPATH=... - AI usage guidelines: when the user specifies a save path, automatically use the
--out-dirparameter - Parameters:
url(required)--audio-only/--audio-format--subtitles(optional, automatically download subtitles)--sub-lang(optional, subtitle language, default all)--cookies(optional)--cookies-from-browser(optional, chrome/firefox/safari/edge, mutually exclusive with--cookies)--proxy(optional)--out-dir(optional, custom output directory)
- Based on
-
scripts/download_douyin_note.py- Douyinimage-text notesimage downloader (the video stream interface returns only the first image for image-text, so image-text goes through image extraction separately)
- Note: the old version it depends on
iteminfoAPI has been add by Douyinencrypt_data_missBlocked, current extraction capability is limited; take a manual screenshot if necessary
-
scripts/download_douyin_video_nocookie.py- DouyinVideoNo-login direct downloader (
aweme.snssdk.com/v1/play, no cookie/signature needed) download_media.pyIt is automatically invoked when Douyin yt-dlp fails; it can also be used independently- The output also ends with
SAVED_FILEPATH=, making it easy for downstream scripts (cubox/content-manager) to parse - Parameters:
url(required),--out-dir、--ratio(540p/720p/1080p, default 540p),--out-name - For the principle and boundaries, see
references/douyin-nocookie-approach.md
- DouyinVideoNo-login direct downloader (
Dependencies
System dependencies
| Dependency | Installation method |
|---|---|
yt-dlp |
pip install yt-dlp |
ffmpeg(optional, used for subtitle extraction and audio conversion) |
macOS: brew install ffmpegLinux: sudo apt-get install ffmpeg |
aria2c(optional, Douyin fallback multi-threaded acceleration for large files + resumable downloads; automatically falls back to single-threaded if not installed) |
macOS: brew install aria2 |
Python packages
No additional Python dependencies are required;yt-dlp already includes the required libraries.
The Douyin-related scripts (download_douyin_*.py) additionally depend on requests(pip install requests)。