Documentation site: mdBook user + contributor guide (2.2)
An mdBook under docs/ rendering eight pages: introduction, installation, first-run/config, downloading, an anti-bot guide that captures the hard-won cookies/curl_cffi/POT/player-client knowledge, troubleshooting (the nine error classes + non-download issues), architecture (the two-front-ends/one-engine design, settings flow, layout invariant, persistence), and packaging. - .forgejo/workflows/docs.yml builds the book and publishes docs/book/ to the `pages` branch for Codeberg Pages on docs/ changes. - docs/book/ is gitignored (rendered output). - README: fix the stale backup.directory comment — every platform nests under the one library root, not a channels/ sibling split. - Add CLAUDE.md (repo guidance for Claude Code). Builds clean with mdbook 0.5; intra-doc anchor links verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
7906d7d07f
commit
e06c2ef826
14 changed files with 833 additions and 1 deletions
97
docs/src/anti-bot.md
Normal file
97
docs/src/anti-bot.md
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
# Staying ahead of YouTube's bot detection
|
||||
|
||||
YouTube increasingly fingerprints and rate-limits automated clients.
|
||||
yt-offline ships a layered defense; understanding the layers makes the
|
||||
difference between "everything downloads" and "constant captchas."
|
||||
|
||||
In rough order of impact:
|
||||
|
||||
## 1. Be logged in (cookies)
|
||||
|
||||
This is the single biggest factor. **Anonymous requests get captcha-
|
||||
walled the hardest.** Provide a `cookies.txt` exported from a browser
|
||||
where you are **signed in to YouTube**, or point yt-offline at the
|
||||
browser profile directly.
|
||||
|
||||
A *valid* logged-in jar contains the auth cookies `SID`, `SAPISID`,
|
||||
`__Secure-1PSID`, `__Secure-3PSID`, `LOGIN_INFO`, etc. A jar with only
|
||||
`VISITOR_INFO1_LIVE`, `PREF`, `YSC` is **anonymous** — it's not signed in
|
||||
and actually makes detection *worse* than no cookies. yt-offline's
|
||||
Settings → Cookies panel warns you when your jar is anonymous or expired.
|
||||
|
||||
Two ways to supply cookies:
|
||||
|
||||
- **Export a `cookies.txt`** with a browser extension like *Get
|
||||
cookies.txt LOCALLY*, then paste/upload it in Settings → Cookies. A
|
||||
file in the working directory takes precedence over the browser option.
|
||||
- **Read the browser profile live** by setting the cookie browser to a
|
||||
yt-dlp `--cookies-from-browser` spec. Plain `firefox`/`chrome`/`brave`
|
||||
works for default profiles; for a non-default profile (e.g. Brave's
|
||||
beta channel) use the full form:
|
||||
|
||||
```
|
||||
brave:/home/you/.config/BraveSoftware/Brave-Origin-Beta
|
||||
```
|
||||
|
||||
The path is the **profile root** (yt-dlp appends the `Default`
|
||||
subdirectory itself). The advantage: cookies are read fresh from the
|
||||
live session each download, so they never go stale.
|
||||
|
||||
> Cookies are session credentials — yt-offline never commits or transmits
|
||||
> `cookies.txt` unprompted, and redacts the cookie path out of any log
|
||||
> line shown in the UI.
|
||||
|
||||
## 2. TLS impersonation (curl_cffi)
|
||||
|
||||
yt-dlp's `--impersonate` makes requests carry a real browser's TLS
|
||||
fingerprint (via `curl_cffi`), so the connection doesn't *look* like a
|
||||
script. The bundled install sets this up automatically and yt-offline
|
||||
picks an impersonation target per platform.
|
||||
|
||||
If impersonation silently does nothing, it's almost always a
|
||||
**yt-dlp ⇄ curl_cffi version mismatch** — which is exactly why the
|
||||
bundled install uses **nightly** yt-dlp (it accepts current curl_cffi;
|
||||
stable lags and disables all impersonate targets when a newer curl_cffi
|
||||
is present). See
|
||||
[Troubleshooting → impersonation](./troubleshooting.md#impersonate-targets-show-unavailable).
|
||||
|
||||
## 3. POT tokens (Proof-of-Origin)
|
||||
|
||||
YouTube increasingly binds a per-video **Proof-of-Origin token** to
|
||||
playback; without one, format URLs come back empty. yt-offline can run
|
||||
[bgutil-pot](https://github.com/jim60105/bgutil-ytdlp-pot-provider-rs), a
|
||||
loopback HTTP server that mints these tokens, and point yt-dlp at it.
|
||||
|
||||
Enable **Settings → Use POT token provider** (requires the bundled
|
||||
yt-dlp; the matching plugin installs into its venv) and click **Install**.
|
||||
|
||||
> **Version-skew footgun:** the yt-dlp plugin must come from the *same
|
||||
> release* as the bgutil-pot server binary — **not** the PyPI package,
|
||||
> which versions independently and silently produces no tokens on a
|
||||
> mismatch. yt-offline's installer handles this by unpacking the
|
||||
> version-matched plugin zip from the server's release.
|
||||
|
||||
## 4. Player-client selection
|
||||
|
||||
YouTube cracks down on different internal "player clients" over time —
|
||||
the `web` client is currently the most captcha-prone, while `tv` and
|
||||
`mweb` are the least. yt-offline no longer forces `web`; it lets yt-dlp
|
||||
pick good defaults. If a specific channel keeps hitting captchas, set a
|
||||
client override (global or per-channel):
|
||||
|
||||
```
|
||||
tv,mweb
|
||||
```
|
||||
|
||||
## 5. Throttling
|
||||
|
||||
A burst of ~30 rapid requests is a classic trip-wire. yt-offline inserts
|
||||
a small jittered pause between videos (a fixed cadence looks robotic; a
|
||||
random one looks human) and, after any rate-limit hit, triples the
|
||||
sleeps for the rest of the batch before recovering.
|
||||
|
||||
---
|
||||
|
||||
**TL;DR for a clean setup:** bundled (nightly) yt-dlp + fresh
|
||||
**logged-in** cookies + POT provider enabled. That combination resolves
|
||||
the vast majority of captcha / "Video unavailable" failures.
|
||||
Loading…
Add table
Add a link
Reference in a new issue