How Agent Reach Switches Between yt-dlp and bili-cli for YouTube and Bilibili Backends

Agent Reach dynamically selects between yt-dlp for YouTube and layered fallbacks including bili-cli for Bilibili by probing runtime environments and validating dependencies at startup.

The Agent Reach repository implements a channel-based abstraction that treats YouTube and Bilibili as distinct platforms requiring different backend strategies. While YouTube relies exclusively on yt-dlp with environment validation, Bilibili employs a cascading fallback system through bili-cli, OpenCLI, and a zero-dependency search API. This architecture ensures maximum compatibility across diverse host environments while providing clear remediation paths when dependencies are missing.

YouTube Backend: yt-dlp with JavaScript Runtime Validation

The YouTube implementation in agent_reach/channels/youtube.py does not switch between alternative backends. Instead, it performs rigorous environment validation to ensure yt-dlp can execute successfully, reporting granular status messages when dependencies are missing.

Probing the yt-dlp Executable

The check() method initiates validation by calling probe_command to verify the yt-dlp binary exists and executes correctly. According to the source in agent_reach/channels/youtube.py (lines 35-48), this probe distinguishes between three states: installed, missing, or broken. When the executable is present and functional, the channel sets self.active_backend = "yt-dlp" and proceeds to validate JavaScript capabilities.

Validating JavaScript Runtimes

YouTube's encrypted pages require a JavaScript runtime. The channel scans the PATH for deno or node executables (lines 51-53). If deno is found, validation passes immediately. When only node is detected, the system performs additional configuration checks to ensure compatibility.

Configuration Checks for Node.js

When Node.js is the sole available runtime, Agent Reach verifies that the user has explicitly enabled JavaScript support via configuration. The code reads the yt-dlp configuration path using get_ytdlp_config_path() from agent_reach/utils/paths.py, then checks for the --js-runtimes flag through the _has_js_runtime_config helper (lines 58-65). If this flag is absent, the channel returns a warning with instructions generated by render_ytdlp_fix_command().

Once all checks pass, the channel reports "ok" status and optionally appends transcription capability information based on Whisper provider availability and ffmpeg presence (lines 67-78).

Bilibili Backend: Multi-Layered Fallback Strategy

Unlike YouTube, the Bilibili channel in agent_reach/channels/bilibili.py implements dynamic backend switching through an ordered list of candidates. The check() method iterates over self.ordered_backends(config), which yields ["bili-cli", "OpenCLI", "B站搜索 API"] (lines 51-58), selecting the first functional option.

Primary Backend: bili-cli

The bili-cli tool provides a stable, login-free interface to Bilibili content. The validation occurs in _check_bili_cli, which invokes probe_command("bili", ["--version"], ...) (lines 82-90).

  • If the command is missing, the backend is skipped silently
  • If present but broken, the method returns an error status
  • If successful, the channel sets self.active_backend = "bili-cli" and advertises full functionality including search, hot videos, ranking, video details, and audio extraction

Secondary Backend: OpenCLI

When bili-cli is unavailable, the channel attempts OpenCLI integration via opencli_status() from agent_reach/backends/opencli.py (lines 96-101). This backend leverages browser sessions to extract subtitles and metadata. If OpenCLI reports ready status, it becomes the active backend with subtitle support capabilities.

Fallback: Bilibili Search API

The zero-dependency fallback performs a lightweight HTTP request to the public _SEARCH_API endpoint. The _check_search_api method validates reachability by checking for a JSON response with code: 0 (lines 24-33). This ensures basic functionality even when no external CLI tools are installed.

Aggregation of Broken Backend Warnings

The channel implements sophisticated error handling when higher-priority backends fail but lower-priority ones succeed. It aggregates broken_notes from failed checks and appends them to the final status message (lines 62-71), alerting users that bili-cli or OpenCLI is broken while still permitting operation through the Search API.

Why Agent Reach Implements Dynamic Backend Switching

The architectural divergence between platforms stems from reliability requirements. YouTube maintains stable yt-dlp support—the only variable is the JavaScript runtime environment. The channel reports detailed warnings when Node.js or Deno is missing rather than attempting fallbacks, as yt-dlp remains the definitive solution for the platform.

Bilibili required a different approach. As noted in the bilibili.py file header, yt-dlp access was blocked (HTTP 412 errors) as of mid-2026, rendering the previous extraction method non-viable. The layered fallback ensures functionality across network conditions: bili-cli provides the richest feature set, OpenCLI adds browser-based extraction, and the Search API guarantees basic search capability without external dependencies.

Code Examples

Detect YouTube backend status and JavaScript runtime availability:

from agent_reach.channels.youtube import YouTubeChannel

yt = YouTubeChannel()
status, msg = yt.check()  # Probes yt-dlp and validates Deno/Node

print(f"Status: {status}")  # "ok", "warn", "error", or "off"

print(msg)                # Human-readable advice on JS runtime installation

Query Bilibili with automatic backend selection:

from agent_reach.channels.bilibili import BilibiliChannel

bl = BilibiliChannel()
status, msg = bl.check()  # Tries: bili-cli → OpenCLI → Search API

print(f"Active backend: {bl.active_backend}")
print(f"Status: {status}")
print(msg)

Extract transcripts using the validated YouTube backend:

from agent_reach.channels.youtube import YouTubeChannel

transcript = YouTubeChannel().transcribe(
    "https://youtube.com/watch?v=example",
    provider="auto"
)
print(transcript[:200])  # First 200 characters of transcription

Summary

  • YouTube uses yt-dlp exclusively with pre-flight checks for JavaScript runtimes (Deno preferred, Node.js requires --js-runtimes configuration)
  • Bilibili implements a three-tier fallback: bili-cli → OpenCLI → Search API, selected dynamically based on environment capabilities
  • The check() method in both channels probes external dependencies via probe_command and reports granular status ("ok", "warn", "error", "off")
  • Failed high-priority backends on Bilibili generate warnings while allowing low-priority fallbacks to function
  • All backend validation logic resides in agent_reach/channels/youtube.py and agent_reach/channels/bilibili.py, with utility functions in agent_reach/probe.py and agent_reach/utils/paths.py

Frequently Asked Questions

How does Agent Reach detect if yt-dlp is properly installed?

The YouTube channel calls probe_command from agent_reach/probe.py with the executable name and version flag. This helper runs the command in a subprocess and categorizes the result as installed, missing, or broken based on return codes and output parsing (lines 35-48 in youtube.py).

Why does Bilibili require multiple backend options while YouTube does not?

According to the source code comments in bilibili.py, yt-dlp support for Bilibili was blocked via HTTP 412 responses in mid-2026. The maintainers removed yt-dlp from the Bilibili channel entirely, necessitating alternative extraction methods. YouTube continues to work reliably with yt-dlp, requiring only JavaScript runtime validation rather than backend substitution.

What happens if Node.js is installed but not configured for yt-dlp?

When Node.js is detected without the --js-runtimes flag enabled in the yt-dlp configuration file, the YouTube channel returns a "warn" status. It generates a specific fix command via render_ytdlp_fix_command() that instructs the user to either install Deno or add the required flag to the configuration file at get_ytdlp_config_path() (lines 58-65).

Can I force Agent Reach to use a specific Bilibili backend?

The ordered_backends(config) method generates the priority list dynamically, but the channel selects the first working backend automatically. Users cannot force a specific backend if it fails the probe_command check or opencli_status() validation, ensuring only functional backends are activated. However, installing bili-cli ensures it takes precedence as the primary candidate.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →