Observed since 21 Oct, 08:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
agent-video-downloader
yt-dlp for agents: a cloud-CLI multi-agent video downloader for TikTok, Instagram, Douyin, Rednote, Reddit, X.com
yt-dlp for cloud AI agents. One command downloads videos from TikTok, Instagram, Douyin, Rednote (Xiaohongshu), Reddit, X.com — no browser, no cookies, no login. Built for Claude / Cursor / Cline / GLM / GPT agents that need video bytes in task workflows.
Install:
pip install agent-video-downloader
avd agent-setup
Live on PyPI: https://pypi.org/project/agent-video-downloader/
pip install agent-video-downloader
avd agent-setup
avd download 'https://www.tiktok.com/@anyuser/video/<numeric-id>'
avd agent-setup auto-installs ffmpeg, all Python deps, and the XHS-Downloader repo (for Rednote). It's idempotent — safe to re-run anytime. Zero manual steps for an AI agent.
For the full agent usage guide (8 steps, decision tree, MCP server config, env vars):
avd agent-instructions
yt-dlp is broken from datacenter IPs for TikTok, Twitter, Reddit, Instagram, Douyin. Cloud CLI agents (Claude Code, GLM CLI, Cursor, Cline) that need to download videos for tasks (transcription, OCR, content analysis, archival) have no reliable path. avd fixes that with direct-API fallback chains that work from cloud IPs without login.
All six platforms download real video bytes (verified live 2026-10-03 from a Hong Kong datacenter IP, total 1.2 GB downloaded through avd itself):
| Platform | Method | Sample download |
|---|---|---|
| TikTok | TikWM mirror API | 2.0 MB / 10.5 s |
| Twitter/X | api.fxtwitter.com → video.twimg.com | 156 MB / 74.8 s 4K |
| rapidsave.com + v.redd.it CMAF/DASH + ffmpeg mux | 6.1 MB / 16.1 s | |
| yt-dlp + facebookexternalhit/1.1 UA | 8.4 MB / 77.3 s | |
| Douyin | api.douyin.wtf public demo (zero-config) | 3.6 MB / 27.6 s |
| Rednote (XHS) | XHS-Downloader (curl_cffi chrome146) | 8.4 MB / 720p |
avd itselfA 24-URL batch (4 per platform minimum, large videos first) was run through avd itself to validate the system on real public content rather than curated samples:
Total: 1.2 GB of real video content downloaded through avd itself.
| Command | Purpose |
|---|---|
avd agent-setup | One-command bootstrap — installs ffmpeg, deps, XHS-Downloader |
avd agent-instructions | Print step-by-step usage guide for AI agents |
avd download <url> | Download one URL |
avd batch <file> | Batch download (one URL per line, # comments OK) |
avd verify <path> | Verify a downloaded file's integrity |
avd test --smoke | End-to-end self-test on one URL per platform |
avd jobs | List recent jobs |
avd dlq | List dead-letter queue entries |
avd replay <dlq_id> | Replay a failed job |
avd mcp | Start MCP server (stdio JSON-RPC 2.0) |
avd supported | Show supported platforms |
avd agents | Show agent versions |
pip install agent-video-downloader
avd agent-setup
git clone https://github.com/hamza140202/agent-video-downloader
cd agent-video-downloader
pip install -e .[dev]
avd agent-setup
ffmpeg / ffprobe (auto-installed by avd agent-setup on Debian/Ubuntu; manual on other systems)git (for cloning XHS-Downloader on first Rednote download)| Var | Default | Description |
|---|---|---|
AVD_DOWNLOAD_DIR | ./download | Default download destination |
AVD_LOG_LEVEL | INFO | DEBUG/INFO/WARNING/ERROR |
AVD_REDDIT_CLIENT_ID | — | Reddit OAuth (only needed if rapidsave.com fails — rare) |
AVD_REDDIT_CLIENT_SECRET | — | same |
AVD_REDDIT_USERNAME | — | throwaway Reddit username |
AVD_REDDIT_PASSWORD | — | throwaway Reddit password |
AVD_DOUYIN_DTK_URL | — | self-hosted Evil0ctal DTK (optional — defaults to public demo) |
AVD_XHS_DOWNLOADER_PATH | ~/XHS-Downloader | override XHS-Downloader clone path |
AVD_XHS_COOKIE | — | XHS cookie (optional, unlocks HD Rednote videos) |
AVD_PROXY | — | SOCKS5/HTTP proxy URL for all requests |
URL → Orchestrator → [TikTok|Twitter|Reddit|Instagram|Rednote|Douyin] extractors (fallback chain)
→ Verifier (6-layer: size, magic bytes, ffprobe, duration, streams, moov)
→ Truth Agent (cross-check vs source platform: oEmbed / syndication / RSS / OG)
→ verified MP4 + manifest
tests/sample_urls.jsonPer-platform fallback chains (slot-based state machine, ytagent doctrine):
Full design: docs/architecture.md · Full research: docs/research-report.md
README.md — this file (install + quickstart + commands)avd agent-instructions — interactive step-by-step usage guideCLAUDE.md — project memory (read first if modifying)AGENTS.md — agent contracts + perfection prompting rulesTECHSTACK.md — every dependency, every version, whyPHASES.md — development phases with exit criteriaPLAN.md — concrete execution plan with task IDsSKILLS.md — per-agent skill spec sheetsdocs/research-report.md — live-verified endpoint research per platformdocs/architecture.md — system design with ASCII diagramdocs/endpoint-matrix.md — living endpoint tableMIT. See LICENSE.
metadata.extractor_chain and metadata.slots_tried from your run's manifest attachedpip install agent-video-downloader && avd agent-setupavd agent-setup command (auto-install ffmpeg, deps, XHS-Downloader)avd agent-instructions command (8-step AI agent usage guide)avd itself (1.2 GB)verified verdictDownload counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
httpxEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | httpx<1.0,>=0.27 | runtime |
aiofilesEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | aiofiles>=23.0 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pydantic<3.0,>=2.7 | runtime |
pydantic-settingsEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pydantic-settings>=2.3 | runtime |
tenacityEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | tenacity<10.0,>=8.5 | runtime |
pybreakerEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pybreaker<2.0,>=1.3 | runtime |
richEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | rich<14.0,>=13.0 | runtime |
clickEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | click<9.0,>=8.1 | runtime |
python-magicEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | python-magic>=0.4.27 | runtime |
structlogEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | structlog>=24.0 | runtime |
aiosqliteEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | aiosqlite>=0.20 | runtime |
beautifulsoup4Environment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | beautifulsoup4>=4.12 | runtime |
lxmlEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | lxml>=5.2 | runtime |
LevenshteinEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | Levenshtein>=0.25 | runtime |
yt-dlpEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | yt-dlp>=2025.10.0 | runtime |
feedparserEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | feedparser>=6.0 | runtime |
playwrightEnvironment{
"extras": "",
"marker": "extra == \"browser\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | playwright>=1.40; extra == "browser" | runtime |
uvicornEnvironment{
"extras": "",
"marker": "extra == \"http\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | uvicorn>=0.30; extra == "http" | runtime |
fastapiEnvironment{
"extras": "",
"marker": "extra == \"http\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | fastapi>=0.110; extra == "http" | runtime |
mcpEnvironment{
"extras": "",
"marker": "extra == \"mcp\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | mcp>=1.0; extra == "mcp" | runtime |
socksioEnvironment{
"extras": "",
"marker": "extra == \"socks\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | socksio>=1.0; extra == "socks" | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest<10.0,>=8.0; extra == "dev" | runtime |
pytest-asyncioEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-asyncio>=0.23; extra == "dev" | runtime |
pytest-covEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-cov>=5.0; extra == "dev" | runtime |
pytest-mockEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | pytest-mock>=3.12; extra == "dev" | runtime |
respxEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | respx>=0.21; extra == "dev" | runtime |
hypothesisEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | hypothesis>=6.100; extra == "dev" | runtime |
freezegunEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.10",
"evaluation": "NOT_EVALUATED"
} | freezegun>=1.5; extra == "dev" | runtime |
bdist_wheel · 65.99 KB · Python py3
sdist · 49.73 KB · Python source
Shared repository data · GitHub
Observed since 21 Oct, 08:54 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:9cfc578bf86b6a8f4b02271ba2b76a29cbab0da7422532849ec818b0b64fc4eb