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

> Agent Reach intelligently switches between yt-dlp for YouTube and bili-cli for Bilibili by probing environments and validating dependencies at startup. Easily manage your video downloads.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: internals
- Published: 2026-06-17

---

**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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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:

```python
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:

```python
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:

```python
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`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py) and [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py), with utility functions in [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) and [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/youtube.py)).

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

According to the source code comments in [`bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/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.