はじめに
広告ブロッカーは、バナーやポップアップを消すだけの単純なツールだと思われがちだ。だが YouTube の動画内広告(プリロール/ミッドロール)に対しては、その単純なモデルが通用しない。本編動画と広告動画が、同じドメインから、同じ仕組みで配信されるからだ。
では、ブロッカーはどうやって「同じ動画」の中から広告だけを認識して取り除いているのか。本記事では、YouTube が動画を再生するまでのデータの流れを追いながら、その仕組みと、YouTube 側の検出との終わりなき攻防を解説する。
1. 前提:YouTube が動画を再生するまでのデータの流れ
広告ブロックの話に入る前に、YouTube プレイヤーがどう動くかを押さえておく必要がある。
動画ページを開くと、プレイヤーは映像をいきなり流し始めるわけではない。まず YouTube のサーバーに対して player レスポンスと呼ばれる JSON を要求する。エンドポイントは /youtubei/v1/player で、同じ内容はページ HTML 内の ytInitialPlayerResponse というグローバル変数にも初期データとして埋め込まれている。
この JSON には、再生に必要な情報が一式入っている。
-
videoDetails— タイトル、チャンネル、再生時間、視聴回数など -
streamingData— 実際の映像・音声ストリームの URL -
playabilityStatus— 再生可否のステータス -
adPlacements/playerAds/adSlots— どのタイミングで、どんな広告を挿入するかの情報
ポイントはここだ。広告は「あとから別ルートで降ってくる」のではなく、再生開始前のこの JSON にスケジュールとして書き込まれている。プレイヤーはこの広告情報を読み取って、本編の前後や途中に広告を差し込む。
つまり、広告は「映像」である前に、まず「メタデータ(予定表)」として存在している。ここがブロックの突破口になる。
2. 従来の広告ブロックが、そのままでは効かない理由
一般的な Web 広告は、doubleclick.net や googlesyndication.com といった広告専用ドメインから配信される。だから従来の広告ブロッカーは「フィルターリスト(EasyList など)に載っているドメインへの通信をブロックする」という、ネットワークレベルの単純なルールで対処できた。
しかし YouTube の動画内広告は、広告も本編も *.googlevideo.com という同じインフラから配信される。「広告ドメインを丸ごと弾く」をやると本編まで再生できなくなる。送信元ドメインで区別するという従来の武器が、ここでは使えないのだ。
そのため YouTube 広告には、ドメイン遮断とは別の、より踏み込んだ手法が必要になる。
3. ブロッカーの3つの基本戦術
広告ブロッカーは、おおむね次の3つを組み合わせて対処している。
(a) player レスポンスの改変 — 中核となる手法
最も本質的なのがこれだ。前述の player レスポンス JSON がプレイヤーのコードに読まれる前に、adPlacements や playerAds といった広告関連フィールドを削除(または空に)してしまう。すると、プレイヤーは「広告の予定が一件も入っていない動画」として本編をそのまま再生する。
uBlock Origin の場合、json-prune というスクリプトレットがこれを担う。これは JSON レスポンスや JavaScript オブジェクトから、指定したプロパティ(例:adPlacements)を抜き取る汎用フィルターだ。フィルターリストに「YouTube の player レスポンスから広告フィールドを prune せよ」というルールを書くことで実現される。
重要なのは、広告映像そのものをブロックしているのではないという点だ。やっているのは「広告の存在情報を再生前に消す」こと。予定表から広告の行を消せば、そもそも広告は呼び出されない。
(b) スクリプト注入とタイミング
(a) を成立させるには、注入したコードがプレイヤーの初期化コードより先に走る必要がある。ytInitialPlayerResponse はページ読み込み直後にプレイヤーが読み取ってしまうため、それより後にいくら書き換えても手遅れだからだ。
そこでブロッカーは、ページの最初期(ブラウザ拡張でいう document_start のタイミング)にフックを仕込み、
- ネットワークリクエスト(
fetch/XHR)を横取りして、レスポンス本文を書き換えてからプレイヤーに渡す - もしくは
ytInitialPlayerResponse変数を、読まれる前に上書きする
といった処理を行う。人間が手動で消すのでは間に合わない理由がここにある。ミリ秒単位のタイミング勝負なので、機械的に・毎回・自動で割り込む常駐フックが必須になる。
(c) コスメティックフィルタリング — UI の掃除
(a)(b) が動画広告への対処なのに対し、ページ周辺のバナー、ホーム画面の広告枠、検索結果に紛れ込むプロモーション枠などは、CSS で要素を隠す「コスメティックフィルタリング」で処理する。これは動画再生そのものには関与しないが、ページ全体を広告のない見た目にするために併用される。
4. YouTube 側の対抗策:検出(アンチアドブロック)
YouTube はこれを黙って見ているわけではない。ブロッカーの存在を検出してくる。検出スクリプトが動画読み込みのたびに走り、主に次の兆候を見ている。
- 広告リクエストがブロックされていないか
- 本来あるべき広告要素がページから欠落していないか
- ページ読み込みのタイミングに不自然なズレがないか
これらを検知すると、「広告ブロッカーを検出しました」という警告を出したり、連続再生の本数を制限したり、まれに再生そのものを止めたりする。
そこでブロッカー側は、広告を消すと同時に検出スクリプトを無力化する処理も入れる。uBlock Origin の set-constant スクリプトレットは、特定の変数を固定値で上書きするもので、検出フラグを常に「ブロッカー無し」を意味する値に固定するといった使い方ができる。広告除去と検出回避は、つねにワンセットなのだ。
5. さらなる難関:サーバーサイド広告挿入(SSAI)
ここまでの手法は「広告が独立したメタデータ/別ストリームとして存在する」ことを前提にしている。だが **SSAI(Server-Side Ad Insertion、サーバーサイド広告挿入)**はその前提を崩す。
SSAI では、広告がサーバー側で本編映像に繋ぎ込まれ、1本の連続したストリームとして配信される。広告と本編の境目がストリーム上に存在しないため、メタデータをいくら削っても切り離せない。クライアント側でのメタデータ除去という基本戦術が原理的に効かなくなるアプローチであり、ブロッカーにとって最も厄介な方向性とされる。
6. ブラウザ内蔵型と拡張機能型の違い
広告ブロックの実装場所には、大きく2つの系統がある。
拡張機能型(uBlock Origin、AdGuard、Adblock Plus など)は、ブラウザに後付けでインストールする。手軽だが、ブラウザの拡張 API の制約を受ける。とくに Chrome 系で進む Manifest V3 への移行は、ネットワークリクエストをブロック・改変する従来 API(webRequest のブロッキング機能)を制限する方向にあり、ブロッカーの自由度に影響する論点として議論が続いている。
ブラウザ内蔵型(Brave の Shields など)は、ブロック機能をブラウザ本体に組み込んでいる。拡張 API の制約を受けず、ネットワークレベルでの処理を本体側で行えるのが強みだ。一方で、ブロックロジックがブラウザのリリースサイクルに紐づくため、更新の機動力という点では別の制約もある。
どちらの系統も、YouTube の仕様変更に追随するためにフィルターリストやスクリプトレットを頻繁に更新している。
7. まとめ:終わりのないいたちごっこ
YouTube 広告ブロックの核心は、一言でいえばこうだ。
広告映像を「見分けて」消しているのではなく、再生前のメタデータ(予定表)から広告情報を、プレイヤーに読まれる前に取り除いている。
そして、
- ドメイン遮断が効かないので、player レスポンスの改変が主役になる
- それはタイミング勝負なので、最初期に走る自動フックが必須
- YouTube は検出で対抗し、ブロッカーは検出回避で再対抗する
- SSAI のように、前提そのものを崩す手も登場している
この構造ゆえに、ある時点で完璧に動いていたブロックが翌週には一部すり抜ける、という現象が起きる。YouTube が検出と配信方式を更新し、ブロッカーがフィルターを更新し返す——技術的には、双方が相手の前提を崩し合う終わりのない更新合戦として捉えるのが正確だ。