rustypipe-botguard 0.1.2

Run YouTube Botguard challenges and generate PO tokens
Documentation
# ![RustyPipe]https://codeberg.org/ThetaDev/rustypipe/raw/branch/main/notes/logo.svg Botguard

[![Current crates.io version](https://img.shields.io/crates/v/rustypipe-botguard.svg)](https://crates.io/crates/rustypipe-botguard)
[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat)](https://opensource.org/licenses/MIT)
[![Docs](https://img.shields.io/docsrs/rustypipe-botguard/latest?style=flat)](https://docs.rs/rustypipe-botguard)
[![CI status](https://codeberg.org/ThetaDev/rustypipe-botguard/actions/workflows/ci.yaml/badge.svg?style=flat&label=CI)](https://codeberg.org/ThetaDev/rustypipe-botguard/actions/?workflow=ci.yaml)

RustyPipe Botguard is a CLI tool to run YouTube's Botguard challenges and generate
Proof-of-origin tokens (PO tokens).

It is based on the reverse-engineering work of LuanRT
(<https://github.com/LuanRT/BgUtils>).

Since the Botguard challenges are intended to run in a full browser environment and the
dependencies needed to replicate it are quite large, I decided against including it in
RustyPipe directly and instead released it as a seperate CLI tool. This also has the
advantage that rustypipe-botguard can be integrated into any YouTube downloader/client.

## How it works

Since August 2024 YouTube requires PO tokens to access streams with web-based clients.
Otherwise streams will return a 403 error.

PO tokens are used by YouTube as proof that the user is accessing YouTube from a real
browser. The tokens are generated by a proprietary virtual machine implemented in
JavaScript. The process works as follows:

- Fetch the VM script and Botguard program from YouTube's API (`api/jnn/v1/Create`)
- Load the VM script into the JS environment
- Run the program using the VM and submit the result to YouTube's
  `api/jnn/v1/GenerateIT`endpoint
- YouTube returns an integrity token
- The VM script generates PO tokens using the integrity token and an identifier

RustyPipe-Botguard uses a stripped-down version of the Deno JavaScript runtime along
with JSDOM to replicate a browser environment and pass Botguard challenges. It can also
store a snapshot of its JS environment after successfully solving a challenge. This
greatly speeds up subsequent requests.

PO tokens are currently used in the following places when fetching YouTube videos:

- Player requests need a `serviceIntegrityDimensions.poToken` parameter set to a
  content-bound token (video ID as an identifier)
- Stream URLs need to have a `pot` URL parameter with a session-bound PO token (using
  the visitor data ID as an identifier)

## Usage

Call rustypipe-botguard with one or multiple identifiers as arguments. The tool returns
a list of PO tokens separated with a space.

After the tokens it outputs a space-separated list of metadata items in the format
`key=value`:

- `valid_until`: Unix timestamp when the PO token will expire
- `from_snapshot`: true if the Botguard runtime was created from a snapshot

More metadata items may be added in the future, so your implementation has to ignore
unknown keys.

Since YouTube video IDs can start with a dash and may be interpreted as CLI options, you
should use a double dash seperator between the options and the identifiers.

```sh
$ rustypipe-botguard -- pPvd8UxmSbQ Cgtnelk4ZmJWMXN4cyjpmYi9BjIKCgJERRIEEgAgNA%3D%3D
MlOClAt8t6x0HYKon9J8I-SCEWj3aOQKzLam6LXdLRXW3ypcXHdygoyg4slY9Z9kW0HXdWGKbBep7vWCgE2rjynS1YrhUJYiQfCZTS7FqeJz3MEFIg== MnR3PvWN5T_RRHcCYSMusEHb5MIJmbaZae9TQkssf4Zzht_2ooYgESn5F2OmBM33_hgi3597PoQMtwAofrz5HIyLICAfocSxBZCT1frOBEoXUIOMeXjtctrmfccXNJn9kFq0IvboUu2uKbAYQVVKjHa4gxmoSQ== valid_until=1738715307 from_snapshot=false
```

### Options

- `--snapshot-file` By default, rustypipe-botguard stores its snapshot in the RustyPipe
  data folder located at `~/.local/share/rustypipe/bg_snapshot.bin`. If you want to
  specify a custom file path, use this option.
- `--no-snapshot` Do not load/store a snapshot of the Botguard runtime.
- `--user-agent` Set a custom user agent for fetching Botguard challenges.

### API version

When rustypipe-botguard is called with the --version flag, it outputs both the
application version and API version. Currently the API version is 1 and it will be
incremented with every breaking change. This output can be used to auto-discover the
rustypipe-botguard application without any user input.

```sh
$ rustypipe-botguard --version
rustypipe-botguard 0.1.0
rustypipe-botguard-api 1
```

## Integrations

As a command line tool, RustyPipe Botguard can be easily integrated into any YouTube
client application.

### RustyPipe

By default, RustyPipe automatically detects `rustypipe-botguard` if it is available. If
your Botguard application is located at a different path, you can set it with the
`.botguard_bin(path)` option.

### YT-DLP

To use rustypipe-botguard with yt-dlp, you have to install the plugin
`yt-dlp-get-pot-rustypipe`.

The plugin can be configured using extractor arguments, for example
`--extractor-args 'youtube:rustypipe_bg_pot_cache=1;rustypipe_bg_bin=/path/to/rustypipe-botguard'`.

**Options:**

- `rustypipe_bg_bin`: Custom path to rustypipe-botguard binary.
- `rustypipe_bg_snapshot_file` Custom path to load/store a snapshot of the Botguard runtime.
- `rustypipe_bg_no_snapshot` Do not load/store a snapshot of the Botguard runtime (default: `false`).
- `rustypipe_bg_pot_cache` Reuse generated session PO tokens (default: `true`).
- `rustypipe_bg_user_agent` Set a custom user agent for fetching Botguard challenges.