Skip to content

YouTube

valk edited this page Oct 2, 2026 · 1 revision

YouTube works with no setup. This page is for when it stops.

YouTube decides what to serve by the address asking. A server address it doesn't trust, which includes many hosting providers, is refused however correctly it asks, and the refusals don't look like they are about the address: "requires login", HTTP 400, no audio formats, "the page needs to be reloaded", 403 on the stream itself.

How a track is read

  1. Directly, from your server, with no keys: the VISIONOS client, then the embedded player for videos made for kids or age-restricted ones that allow embedding.
  2. SABR, a second direct try, when youtube.sabr is on and a po-token pair is available.
  3. The backend, when youtube.fallback-api is on. It asks from its own address and mints its own token.

A video YouTube refuses in your server's country is remembered, and later plays go straight to the backend. Age-restricted videos use the backend even with fallback-api off. Searches and playlists are listed by youtube-source, which never plays a track itself.

When a track is blocked in your region and nothing can play it, the first available upload of the same track is used instead, and the player is told so.

With debug: true in config.yml, the console names the path each track took.

The first thing to try

# sources.yml
youtube:
  fallback-api: true

It is on by default, and CDisc switches it on once at startup if it was off. Set it back to false and it stays that way. Nothing else needs configuring for it: no po-token, no visitor data, no keys.

youtube:
  proxy: false

With proxy: true the backend reads the audio itself instead of handing back a link. Turn it on together with fallback-api unless both sides share an address: a stream link is bound to the address that asked for it, and answers anyone else with 403. It costs the backend about a megabyte per minute. Servers located in Russia get it switched on once at startup.

Without the backend: po-tokens

If you'd rather not depend on the backend, YouTube wants proof that requests come from a real browser: a po-token and the visitor-data it belongs to. They only work as a pair.

They are used in this order:

  1. the pair in tokens.yml;
  2. the pair CDisc used last;
  3. the token server at youtube.po-token-backend.url in sources.yml.

A token server is a small Node service that mints a fresh pair in a headless browser. A public one ships in sources.yml; you can run your own and put its URL and password there. CDisc keeps the identity it gets signed by itself and comes back only when YouTube stops honouring it.

With that URL blank and tokens.yml empty, YouTube cuts every track short after about a minute.

A pair by hand

Works for a few weeks, then has to be done again.

  1. Open a private browser window, not signed in, and go to youtube.com.
  2. Open DevTools (F12), the Network tab, and type v1/player into the filter. Do this before the next step: the tab records only while it is open.
  3. Play any video, for example "me at the zoo".
  4. Click the player?prettyPrint=false request, open Payload, then view source, then Show more at the bottom if it is there.
  5. In that JSON, find the poToken and visitorData fields. If poToken is missing, the request went out before the bot check: play another video and take a later request.
  6. Put them into youtube.po-token and youtube.visitor-data in tokens.yml, then /cdisc admin reload.

Other settings

All in sources.yml under youtube, and each is explained beside it.

Setting Meaning
clients Clients youtube-source asks, in order
log-client-failures Logs every rejected format. Noisy, but the only way to tell "needs a token" from "needs a login" from "undecodable format"
setup-guide-url Where operators are pointed when YouTube refuses everything
sabr The SABR second try. Needs the po-token pair
web-client-version, signature-timestamp What SABR claims to be. Bump both together if SABR starts being refused
fast-create Skips the playability check when making a disc. Several times faster
probe-timeout-seconds How long that check waits, with fast-create: false
remote-cipher.url Asked only when CDisc can't solve a signature itself. Blank to never ask

Why one track won't play

  • Private or deleted. Nothing can play it.
  • Region-locked. Judged by your server's address, not the player's. The backend may be in a different country.
  • Blocked by the rights holder. No stream is handed out.
  • A live stream. Plays, with no length and no seeking.

/cdisc admin doctor shows which path works on your server. See Troubleshooting.

Clone this wiki locally