空っぽの <div> がずらりと並んだHTMLが返ってきて、欲しいデータは一行も入っていない。requests.get("https://www.youtube.com/...") を投げてBeautifulSoupで動画タイトルを引っ張ろうとした人なら、この光景に覚えがあるはずです。正直、最初は誰でもがっかりします。
YouTubeを初めてスクレイピングする開発者は、ほぼ間違いなくここでつまずきます。YouTubeはシングルページアプリケーションで、中身のほとんどをクライアント側のJavaScriptで描き出すからです。Pythonスクリプトが受け取るHTMLは、言うなれば外殻だけ。本物の動画タイトルも再生回数もメタデータも、ytInitialData という巨大なJSONの固まりに詰め込まれていて、ページ読み込み後にJSの手で注入されます。
そういうわけで、見るからに正解っぽい soup.find("div", class_="ytd-video-renderer") は None を返します。その要素は、生のHTTPレスポンスの段階ではそもそも存在しないのです。この仕掛けが腑に落ちた瞬間、ばらばらだった点が一本につながりました。これから紹介する4つの手法は、何度も壊しては直しを繰り返し、GitHubのissueを読みあさった末に行き着いた結論です。それぞれの出番を丁寧に切り分けたうえで、最後には「環境構築なんて面倒、とにかくデータだけ寄こせ」という人向けのノーコードの抜け道も用意しています。
そもそも、なぜPythonでYouTubeをスクレイピングするのか?
YouTubeを単なる動画サイトと侮ってはいけません。その正体は、月間25.8億人のアクティブユーザーを抱える巨大なデータの源泉です。51億本超の動画が積み上がり、しかも毎分500時間以上が新たにアップロードされているのですから、企業・研究者・クリエイターがプログラムで解析したくなる公開情報は、それこそ無尽蔵にあります。
ところが、YouTube標準の分析機能で覗けるのは自分のチャンネルのデータに限られます。競合の投稿ペースを掴みたい、自分の業界で勢いづいている話題を追いたい、他人の動画のコメントから視聴者の本音を探りたい――こういう望みを叶えるには、スクレイピングに頼るしかありません。
現場でよく見かける用途を挙げると、こんな具合です。
| 用途 | 必要とする人 | 対象データ |
|---|---|---|
| 競合分析 | マーケティングチーム、コンテンツ戦略担当 | 再生回数、投稿頻度、エンゲージメント率 |
| リード獲得 | 営業チーム、B2B営業 | チャンネルの連絡先情報、説明欄のビジネスメール |
| 市場調査 | プロダクトマネージャー、アナリスト | トレンドトピック、コメントから見える視聴者の反応 |
| コンテンツ戦略 | YouTuber、代理店 | 伸びているフォーマット、効果的なタイトル・タグの傾向 |
| SEO / キーワード調査 | SEO担当者 | 動画タイトル、タグ、説明文、ランキングシグナル |
| ブランドモニタリング | PRチーム、ブランド担当 | 動画タイトル、コメント、説明文に出る自社名言及 |
| 学術研究 | 研究者、データサイエンティスト | 感情分析 用のコメントデータセット(ある2025年の研究では、45K件のYouTubeコメントでBERTをファインチューニングし、93.1%の精度を達成) |
一例として、DJI・GoPro・Insta360を並べた競合分析では、DJIのYouTube到達数が3億9,000万ビューに達し、残り2社の合計をしのいだという結果が報告されています。こうした気づきは、YouTube Studioの画面をいくら眺めていても決して浮かび上がってきません。
なぜ requests + BeautifulSoup だけではYouTubeをスクレイピングできないのか
実際の手順へ進む前に、王道のやり方がなぜコケるのかを腹落ちさせておきましょう。理屈っぽい話に思えても、これを知っておくだけでデバッグの何時間ぶんもが浮きます。
「素直に書く」と、頭の中ではだいたいこんなコードになります。
import requests
from bs4 import BeautifulSoup
response = requests.get("https://www.youtube.com/@somechannel/videos")
soup = BeautifulSoup(response.text, "html.parser")
videos = soup.find_all("a", id="video-title-link")
print(len(videos)) # 0 — 毎回こうなる
返り値は、何度やってもゼロです。ScrapeOps のデバッグ解説も「ページが動的に読み込まれているため、requestsでは歯が立たない」と指摘しています。Teclado の入門ガイドはもっと身も蓋もなく、「requests と BeautifulSoup だけではJavaScriptは実行できない」と言い切っています。
Scrapfly の2026年版YouTube解析記事は、その理屈をこう噛み砕きます。YouTubeはSingle Page Application(SPA)として組まれていて、通常のHTTPリクエストでは初期HTMLの殻が返るだけ。肝心のコンテンツは、まだ描画されていません。動画データはJavaScriptオブジェクトの内側に潜んでいて、ブラウザがそれを実行してDOMへ流し込むのです。
ただ、救いもあります。YouTubeは必要なデータを生のHTMLにちゃんと埋め込んでいるのです。DOM要素としてではなく、<script> タグ内に潜む2つのJSONブロブという形で。
ytInitialData— ページ構造、動画一覧、エンゲージメント指標、コメント継続用トークンytInitialPlayerResponse— 動画の中核メタデータ(タイトル、説明文、長さ、フォーマット、字幕)
このどちらも、requests.get() ひとつあれば手に入ります。ブラウザは要りません。要は、どこを掘ってどうパースするかさえ分かればいい。それが、のちほど扱う方法1です。
PythonでYouTubeをスクレイピングする4つの方法: 一覧比較
それぞれの手法に踏み込む前に、まず判断軸を整理しておきます。私は4つすべてを実際に走らせ、現場でツールを選ぶときに効いてくる基準で突き合わせました。
| 比較項目 | requests + BS4 (ytInitialData) | Selenium / Playwright | yt-dlp | YouTube Data API | ノーコード(Thunderbit) |
|---|---|---|---|---|---|
| セットアップ難易度 | 低い | 中 | 低い | 中(APIキーが必要) | なし |
| JSレンダリング対応 | 一部対応(JSON解析) | あり | あり | N/A(構造化API) | あり |
| 速度 | 速い | 遅い | 速い | 速い | 速い(クラウド) |
| ボット対策リスク | 中 | 高い | 低い | なし | 対応済み |
| クオータ / レート制限 | なし(ただしIPブロックあり) | なし(ただし検知あり) | なし | 1日10,000ユニット | クレジット制 |
| コメント抽出 | 難しい | 可能だが複雑 | 標準対応 | 標準対応 | ページ次第 |
| トランスクリプト | なし | 複雑 | あり | なし | なし |
| 最適な用途 | すぐにメタデータが欲しい | 検索結果や動的ページ | 大量メタデータ + コメント | 構造化データを大規模に取得 | 非エンジニア、手早い書き出し |
かいつまむと、こういう棲み分けになります。

実際に取得できるYouTubeデータと、その取得方法は?
これこそ、私が最初から手元に欲しかった対応表です。1つの手法で全項目が揃うわけではありません。だからこの記事は、わざわざ4つの方法を並べているのです。
| データ項目 | BS4 (ytInitialData) | Selenium/Playwright | yt-dlp | YouTube API | Thunderbit |
|---|---|---|---|---|---|
| 動画タイトル | ✅ | ✅ | ✅ | ✅ | ✅ |
| 再生回数 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 高評価数 | ⚠️ 一貫しない | ✅ | ✅ | ✅ | ✅ |
| コメント(本文) | ❌ | ⚠️ 複雑 | ✅ | ✅ | ⚠️ |
| トランスクリプト / 字幕 | ❌ | ⚠️ | ✅ | ❌ | ❌ |
| タグ | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| サムネイルURL | ✅ | ✅ | ✅ | ✅ | ✅ |
| チャンネル登録者数 | ⚠️ | ✅ | ✅ | ✅ | ✅ |
| 投稿日 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 動画の長さ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Shorts固有データ | ❌ | ⚠️ | ✅ | ⚠️ | ⚠️ |
どの行が自分にとって肝心かで、手法を絞り込んでください。コメントとトランスクリプトが要るなら、yt-dlpがはっきり頭ひとつ抜けています。構造化された統計を中規模で集めたいならAPIが本命です。2分で済ませたいなら、このままThunderbitの節まで飛ばして構いません。

方法1: requests + BeautifulSoup を使って YouTube をスクレイピングする(ytInitialData 解析)
この手は、YouTubeがページデータを生のHTML内のJSONとして埋め込んでいる事実に乗っかります。ブラウザは出番なし。どこを見ればいいかさえ把握していれば事足ります。
- 難易度: 初級
- 所要時間: 約15分
- 必要なもの: Python 3.10以上、
requests、beautifulsoup4
手順1: YouTubeページにGETリクエストを送る
本物のブラウザらしい User-Agent を添えてリクエストします。既定の python-requests/2.x のままだと、即座に弾かれます。ScrapeOps のヘッダー解説も、これを初心者が最も踏みがちな地雷だと位置づけています。
import requests
HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/114.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
"Cookie": "CONSENT=YES+cb", # EUの同意壁を回避
}
url = "https://www.youtube.com/@mkbhd/videos"
response = requests.get(url, headers=HEADERS)
print(response.status_code) # 200 のはず
CONSENT Cookie が要です。これを欠くと、EU圏からのリクエストは consent.youtube.com へリダイレクトされ、ytInitialData がまるごと抜け落ちたHTMLが返ってきます。
手順2: HTMLを解析して ytInitialData スクリプトを見つける
BeautifulSoup でも正規表現でも構わないので、var ytInitialData = を含む <script> タグを探し当てます。
import re
import json
# ytInitialData JSON を抽出
match = re.search(
r"var ytInitialData\s*=\s*({.*?});</script>",
response.text,
re.DOTALL
)
if match:
data = json.loads(match.group(1))
print("ytInitialData の抽出に成功しました")
else:
print("ytInitialData が見つかりません。ヘッダーやCookieを確認してください")
ありがちなしくじりは、終端を }; だけにした非貪欲 .*? を使うこと。JSONの中には入れ子の終端記号が何度も顔を出すので、その手前で打ち切られてしまいます。Scrapfly の2026年版スクレイパーが採るように、終端には };</script> を据えるのが安全です。これは当該スクリプトブロック内で最後の代入にあたるからです。
手順3: JSON構造をたどって動画データを取り出す
JSONはかなりの深さまでネストしています。YouTubeが構造をちょっといじるたびに折れる固定パスを書き込むより、キーを再帰的に探しにいくほうがはるかに丈夫です(YouTubeの構造変更は日常茶飯事で、yt-dlp のissueトラッカーにも2023年以降の変更がいくつも刻まれています)。
def search_dict(partial, search_key):
stack = [partial]
while stack:
cur = stack.pop()
if isinstance(cur, dict):
for k, v in cur.items():
if k == search_key:
yield v
else:
stack.append(v)
elif isinstance(cur, list):
stack.extend(cur)
# チャンネルページから動画情報を抽出
videos = []
for vr in search_dict(data, "videoRenderer"):
videos.append({
"video_id": vr.get("videoId"),
"title": vr["title"]["runs"][0]["text"],
"views": vr.get("viewCountText", {}).get("simpleText", "N/A"),
"published": vr.get("publishedTimeText", {}).get("simpleText", "N/A"),
})
print(f"{len(videos)}本の動画を見つけました")
for v in videos[:5]:
print(f" {v['title']} — {v['views']}")
この再帰的なアプローチは、scrapetube、yt-dlp、Scrapfly がいずれも最終的に落ち着いた解でもあります。YouTubeの頻繁なJSON組み替えに対する耐性の高さが、その理由です。
手順4: 取得したデータをCSVやExcelに書き出す
import csv
with open("youtube_videos.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["video_id", "title", "views", "published"])
writer.writeheader()
writer.writerows(videos)
print("youtube_videos.csv に出力しました")
この方法を使うべき場面、使わない方がいい場面
向いているケース: 数本のチャンネルページや動画ページから、メタデータをさっと拾いたいとき。軽量なSEOツール。タイトル・再生回数・投稿日だけで済む単発分析。
制限: JSON構造は移ろいます。実際に壊れた前例としては、いいねボタンのリファクタリング(2023年: toggleButtonRenderer → segmentedLikeDislikeButtonViewModel)、説明文のリファクタリング(2023年: description.runs[] → attributedDescription.content)、チャンネルのVideosタブの作り直し(2022〜2023年: gridRenderer → richGridRenderer)があります。データセンターIPは、おおむね50〜200リクエストあたりでソフトブロックを食らいがちです。コメントも字幕も拾えません。
方法2: Selenium または Playwright を使って YouTube をスクレイピングする
ページそのものを操作したいとき――検索結果をスクロールしたり、タブをクリックしたり、説明欄を開いたり――はブラウザ自動化の領分です。
- 難易度: 中級
- 所要時間: 約30分
- 必要なもの: Python 3.10以上、Playwright(
pip install playwright && playwright install)または Selenium + ChromeDriver
ゼロから始めるなら、SeleniumよりPlaywrightを推します。TestDino の2026年ベンチマークによれば、PlaywrightはSeleniumと比べて1アクションあたり約1.85倍速く、メモリ消費は約2.1倍少なく、並列実行能力は約4倍とされています。PlaywrightはChrome DevTools Protocolを介した持続的なWebSocket通信を使い、SeleniumはWebDriver over HTTPでコマンドごとに変換層を挟むのが違いです。
手順1: Playwright をセットアップする
pip install playwright
playwright install chromium
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
browser = pw.chromium.launch(headless=False) # 表示ありの方が検知されにくい
context = browser.new_context()
# EUの同意壁を回避するためにCookieを事前設定
context.add_cookies([{
"name": "SOCS",
"value": "CAISNQgDEitib3FfaWRlbnRpdHlmcm9udGVuZHVpc2VydmVyXzIwMjMwODI5LjA3X3AxGgJlbiACGgYIgJnPpwY",
"domain": ".youtube.com",
"path": "/",
}])
page = context.new_page()
手順2: YouTubeページを開いて読み込み完了を待つ
page.goto("https://www.youtube.com/@mkbhd/videos")
page.wait_for_selector("a#video-title-link", timeout=15000)
print("ページが読み込まれ、動画要素が表示されました")
検索結果を狙うなら、https://www.youtube.com/results?search_query=your+query にアクセスします。
手順3: 無限スクロールでさらに動画を読み込む
YouTubeのチャンネルページや検索結果は無限スクロール式です。以下は、Scrapfly のスクロールガイドを下敷きにした定石の scrollHeight ループです。
prev_height = -1
max_scrolls = 20 # ここで上限を設ける。1万本のチャンネルを延々スクロールし続けないため
scroll_count = 0
while scroll_count < max_scrolls:
page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
page.wait_for_timeout(1500) # 新しいコンテンツが読み込まれるのを待つ
new_height = page.evaluate("document.body.scrollHeight")
if new_height == prev_height:
break # 新しいコンテンツが増えていない
prev_height = new_height
scroll_count += 1
print(f"{scroll_count}回スクロールしました")
手順4: レンダリング済みページから動画データを抜き出す
video_elements = page.query_selector_all("a#video-title-link")
videos = []
for el in video_elements:
title = el.inner_text()
href = el.get_attribute("href")
video_id = href.split("v=")[-1] if href else None
videos.append({"title": title, "video_id": video_id, "url": f"https://www.youtube.com{href}"})
print(f"{len(videos)}本の動画を抽出しました")
再生回数や投稿日まで欲しいなら、隣り合う要素も合わせて拾う必要があります。Crawlee の2025年ガイドによると、id="video-title-link" は万能ではなく、YouTubeは複数のページ変種を出し分けています。より粘り強いフォールバックは a[href*="watch"] です。
手順5: CSV や Google Sheets に書き出す
import csv
with open("youtube_playwright.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["title", "video_id", "url"])
writer.writeheader()
writer.writerows(videos)
browser.close()
pw.stop()
この方法を使うべき場面、使わない方がいい場面
向いているケース: 検索結果のスクレイピング、動的なページ要素との対話(タブのクリック、説明文の展開)、完全に描画し終えたDOMが必要な場合。
制限: とにかく遅いです(スクロールして抜く流れだと、1本あたり約1.5〜3秒)。ボット検知のリスクも高めで、素のSeleniumは navigator.webdriver === true をセットするため、JS側の検知にあっさり捕まります。おまけにリソースも食い、ブラウザインスタンス1つで200〜500MBのRAMを抱えます。100本なら、yt-dlpが数秒で片づける作業に3〜8分かかることもあります。
方法3: yt-dlp を使って YouTube をスクレイピングする
yt-dlp は、YouTubeスクレイピング界における万能ナイフのような存在です。youtube-dl のコミュニティフォークで、GitHubスターは157,000超、夜間ビルドも盛んで、メタデータ・コメント・字幕・バッチ処理まで標準で面倒を見ます。しかもブラウザもAPIキーも不要です。
- 難易度: 初級〜中級
- 所要時間: 約10分
- 必要なもの: Python 3.10以上、
pip install yt-dlp
手順1: yt-dlp をインストールする
pip install yt-dlp
ブラウザドライバも、APIキーも、設定ファイルも一切いりません。
手順2: ダウンロードせずに動画メタデータを取得する
import yt_dlp
opts = {
"quiet": True,
"skip_download": True, # 動画本体は取らず、メタデータだけ
"no_warnings": True,
}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
download=False
)
print(f"タイトル: {info['title']}")
print(f"再生回数: {info['view_count']:,}")
print(f"高評価数: {info.get('like_count', 'N/A')}")
print(f"長さ: {info['duration']}秒")
print(f"投稿日: {info['upload_date']}")
print(f"チャンネル: {info['channel']} ({info.get('channel_follower_count', 'N/A')} 登録者)")
print(f"タグ: {info.get('tags', [])[:5]}")
標準的な extract_info は、動画の状態に応じて80〜120項目を返します。中身には id、title、channel、channel_id、channel_follower_count、view_count、like_count、comment_count、upload_date、duration、tags、categories、description、thumbnails、is_live、availability、automatic_captions、subtitles、chapters、heatmap などが並びます。
手順3: YouTube動画のコメントを取得する
opts = {
"quiet": True,
"skip_download": True,
"getcomments": True,
"extractor_args": {
"youtube": {
"max_comments": ["200", "50", "50", "10"], # total, parents, replies-per, replies-total
"comment_sort": ["top"],
}
},
}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
download=False
)
comments = info.get("comments", [])
print(f"{len(comments)}件のコメントを取得しました")
for c in comments[:3]:
print(f" [{c.get('like_count', 0)} likes] {c['author']}: {c['text'][:80]}...")
コメント取得は腰が重いです。yt-dlp Issue #3532では取得速度が約30KB/sと報告されていて、コメント10万件の動画ともなれば何時間も粘ることになります。Issue #11849 には、コメントのページ送りが終わらないうちにフォーマットURLが失効する(約6時間)事例まで記録されています。大物の動画では、max_comments を思い切って絞り込みましょう。
手順4: トランスクリプトと字幕を取得する
YouTube Data API でもBS4でも、完全なトランスクリプトには手が届きません。ここはyt-dlpの独擅場です。
opts = {
"quiet": True,
"skip_download": True,
"writesubtitles": True,
"writeautomaticsub": True,
"subtitleslangs": ["en", "en-orig"],
"subtitlesformat": "json3", # 機械処理しやすい: start/dur(ms)+ text
"outtmpl": "%(id)s.%(ext)s",
}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info(
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
download=False
)
# 字幕データは info 辞書から直接参照できる
auto_captions = info.get("automatic_captions", {})
manual_subs = info.get("subtitles", {})
print(f"自動字幕の言語: {list(auto_captions.keys())[:10]}")
print(f"手動字幕の言語: {list(manual_subs.keys())}")
機械処理を見込むなら json3 形式が重宝します。各セグメントに start / dur がミリ秒単位で入り、テキストも一緒に収まります。言語コードは BCP-47 形式です(en、en-US、zh-Hans、ja、es など)。
手順5: 複数動画やチャンネル全体をまとめてスクレイピングする
opts = {
"quiet": True,
"skip_download": True,
"extract_flat": "in_playlist", # 高速。動画IDとタイトルだけ取得
"sleep_interval": 2,
"max_sleep_interval": 6,
}
with yt_dlp.YoutubeDL(opts) as ydl:
info = ydl.extract_info(
"https://www.youtube.com/@mkbhd/videos",
download=False
)
entries = info.get("entries", [])
print(f"チャンネル内で{len(entries)}本の動画を見つけました")
for e in entries[:5]:
print(f" {e.get('title', 'N/A')} — {e.get('id')}")
チャンネルURL、プレイリストURL、あるいは検索クエリ(ytsearch10:python scraping)を渡せば、ページ送りはyt-dlpが内部でさばいてくれます。
この方法を使うべき場面、使わない方がいい場面
向いているケース: メタデータの大量抽出、コメント、字幕、動画ダウンロード、チャンネルまるごとの取得など、欲しい項目が多岐にわたる場合。
制限: 検索結果ページのスクレイピングはあまり得意ではありません(そこはSelenium/Playwrightに分があります)。2024〜2026年のボット対策強化で、yt-dlpを大規模に回すハードルは上がりました。YouTubeは一部のクライアントに対してBotGuardの認証とPO Tokenを求めるようになっています。本番運用では、bgutil-ytdlp-pot-provider プラグインを噛ませ、--cookies-from-browser chrome を併用するのが定番です。ただし使い捨てアカウントで。yt-dlpチームは、実在のGoogleアカウント由来のCookieを使うと、そのアカウントが凍結されかねないと注意を促しています。
方法4: YouTube Data API を使って YouTube をスクレイピングする
公式の YouTube Data API v3 は、YouTubeデータを取りにいくうえで最も信頼でき、最も構造の整った道です。レスポンスはクリーンなJSONで、項目もドキュメント化されており、ボット対策とのいたちごっことも無縁です。とはいえ、多くの解説が口をつぐむ落とし穴がひとつあります。クオータ制です。
- 難易度: 中級
- 所要時間: 約20分(APIキー設定込み)
- 必要なもの: Python 3.10以上、Google Cloudプロジェクト、
pip install google-api-python-client
手順1: YouTube Data API キーを取得する
- Google Cloud Console にアクセス
- 新しいプロジェクトを作成、または既存のものを選択
- API とサービス → ライブラリ に進み、「YouTube Data API v3」を検索して 有効化
- API とサービス → 認証情報 → 認証情報を作成 → APIキー
- キーをコピーし、下のコードで使います
手順2: 最初のAPI呼び出しを行う
from googleapiclient.discovery import build
API_KEY = "YOUR_API_KEY_HERE"
youtube = build("youtube", "v3", developerKey=API_KEY)
# 特定動画の詳細を取得
response = youtube.videos().list(
part="snippet,statistics,contentDetails",
id="dQw4w9WgXcQ"
).execute()
video = response["items"][0]
print(f"タイトル: {video['snippet']['title']}")
print(f"再生回数: {video['statistics']['viewCount']}")
print(f"高評価数: {video['statistics'].get('likeCount', '非表示')}")
print(f"コメント数: {video['statistics'].get('commentCount', '無効')}")
print(f"長さ: {video['contentDetails']['duration']}")
print(f"タグ: {video['snippet'].get('tags', [])[:5]}")
レスポンスは整然としていて型もはっきり、しかもドキュメント付き。JSONを手探りで掘り起こす必要はありません。
手順3: 動画詳細、チャンネル情報、コメントを取得する
# 動画を検索
search_response = youtube.search().list(
part="snippet",
q="python web scraping tutorial",
type="video",
maxResults=10,
order="viewCount"
).execute()
for item in search_response["items"]:
print(f" {item['snippet']['title']} — {item['id']['videoId']}")
# コメントを取得
comments_response = youtube.commentThreads().list(
part="snippet",
videoId="dQw4w9WgXcQ",
maxResults=20,
order="relevance"
).execute()
for item in comments_response["items"]:
comment = item["snippet"]["topLevelComment"]["snippet"]
print(f" [{comment['likeCount']} likes] {comment['authorDisplayName']}: {comment['textDisplay'][:80]}")
YouTube API のクオータ事情(ここが重要)
ここが、単なるコピペ記事と本当に頼れるガイドとを分かつ分岐点です。標準の割り当ては1日10,000クオータユニットで、太平洋時間の深夜にリセットされます。呼び出しごとのコストは以下のとおりです。
| APIエンドポイント | 1回あたりのクオータ消費 | 1回で取得できる最大件数 |
|---|---|---|
search.list | 100ユニット | 50件 |
videos.list | 1ユニット | 50件の動画ID(まとめて指定可) |
channels.list | 1ユニット | 50件のチャンネルID |
commentThreads.list | 1ユニット | 100件のコメント |
captions.list | 50ユニット | N/A |
では、ざっくり試算してみましょう。検索結果を1,000件取りたいとします。
- 検索呼び出し: 1,000件 ÷ 1ページ50件 = 20回 × 100ユニット = 2,000ユニット(1日の予算の20%が消費)
- その1,000本の動画詳細: 1,000 ID ÷ 1回50件 = 20回 × 1ユニット = 20ユニット(まとめて取れる
videos.listはかなり安い) - その1,000本のコメント(各動画1ページ分だけと仮定): 1,000回 × 1ユニット = 1,000ユニット
控えめなスクレイピングでも、合計はおよそ3,020ユニット。ただし、コメントスレッドが深い動画(1本で50ページ超)が混じると、残り7,000ユニットなどあっという間に蒸発します。コメント5万件の動画なら、約500ページで500ユニット。そんな動画を20本も回せば、その日の枠は使い切りです。
クオータ増量の申請手順はコンプライアンス審査を伴います。プライバシーポリシーURL、利用規約URL、アプリの画面録画、さらにはクオータ計算の根拠まで提出が求められます。コミュニティの報告では、Googleからの初回返信は3〜5営業日ほど、正式承認まで数週間から数か月かかることもあり、「分析用にもっとデータが欲しい」という動機では却下される例も少なくないようです。
APIを使うべき場面: 小〜中規模で、構造化された信頼できるデータが欲しいとき。コメントやチャンネル統計が肝で、クオータ上限を呑み込めるとき。
スクレイピングの方が向いている場面: 大規模案件(1日1万本超)、APIが開示していない項目が欲しいとき(完全なトランスクリプト — captions.download はOAuthと動画所有者の権限が要ります)、あるいは検索1クエリで500件を超えたいとき(totalResults の表示にかかわらず、API側に上限があります)。
ノーコードの近道: Thunderbit で YouTube をスクレイピングする(Python不要)
データパイプラインの一部としてPythonが要るなら、上の方法1〜4が答えです。でも、求めているのが「2分でYouTubeデータ」だけなら話は別。競合分析をしたいマーケターや、プロジェクト環境を立てずにサッと抜きたい開発者なら、もっと素早い道があります。
Thunderbit は、わざわざコードを書くまでもない場面のために用意したAIウェブスクレイパーのChrome拡張です。YouTubeのページ上で、そのまま動きます。
Thunderbit で YouTube を3ステップでスクレイピングする方法
手順1: ThunderbitのChrome拡張 を入れ、YouTubeのチャンネルページ、検索結果ページ、または動画ページを開きます。
手順2: サイドバーの 「AIで項目を提案」 を押します。AIがページを読み取り、動画タイトル、再生回数、投稿日、長さ、チャンネル名、サムネイルURLといった列を提案します。列の追加・削除・名称変更も自在です。
手順3: 「スクレイピング」 を押して、Google Sheets、Excel、CSV、Airtable、Notion へエクスポート。そのまま使えるきれいな表として書き出されます。
こんな人に向いています
- 競合チャンネルのデータは欲しいが、コードは書かないマーケター
- 仮想環境を整えたり依存関係を入れたりせず、すぐデータを取りたい開発者
- ボット対策に阻まれている人 — Thunderbit はユーザー自身のログイン済みブラウザセッションの中でスクレイピングするため、CookieやPO Tokenを引き継げます。これで、サーバー側スクレイパーを苦しめるブロックの多くをすり抜けられます
- Thunderbit は サブページスクレイピング にも対応しているので、各動画ページを開いて、いいね数、説明文、タグなどを表へ追記できます
Thunderbit がYouTubeをどう料理するのか、もっと知りたい方は、Thunderbit YouTube Channel Scraper テンプレート と Thunderbit のYouTubeチャンネル も覗いてみてください。
PythonでYouTubeをスクレイピングしてブロックされないためのコツ
ここに挙げる勘どころは、4つのPython手法すべてに通じます。YouTubeのボット対策はScrapeOps の評価で難易度6/10とされ、主なシグナルは3つ。IPの行動分析、JS実行の要否、そしてころころ変わるHTML構造です。
すべての手法に共通:
- User-Agent だけでなくヘッダー全体をローテーションする —
Accept、Accept-Language、Sec-CH-UAなどのクライアントヒントも、宣言したUAと辻褄を合わせる必要があります。ScraperAPI の2026年ガイド に最新リストがあります。 - リクエスト間に2〜8秒のランダム遅延を入れる。間隔が一定だと、それ自体が検知シグナルになります。
- 数ページ以上を取るなら住宅用プロキシを使う。データセンターIP(AWS、GCP、Hetznerなど)は、2025〜2026年のYouTubeスクレイピングでは実質お手上げです。
- セッションとIPはセットでローテーションする — YouTubeはセッションをIPに紐づけるので、同じCookieが別IPから見えるのは危険信号です。
requests + BS4 の場合: CONSENT=YES+cb Cookie を設定してください。これがないと、EUからのリクエストは同意ページへ送られ、データが取れません。
Selenium/Playwright の場合: Linuxサーバーでは --headless=new より、xvfb を使った表示あり実行のほうが無難です。ヘッドレスChromeは、精緻な検知に対してはなおフィンガープリントを漏らします。playwright-stealth のような、約17種の回避策をまとめて当てるツールも一考の価値ありです。
yt-dlp の場合: sleep_interval と max_sleep_interval を活用しましょう。bgutil-ytdlp-pot-provider プラグインを入れてPO Tokenを生成し、--cookies-from-browser chrome は使い捨てアカウントで使ってください。
API の場合: Google Cloud Console でクオータ消費を見張り、リクエストはまとめて効率化を。videos.list は、50個のIDをカンマ区切りで一度に投げても1ユニットです。使わない手はありません。
Thunderbit の場合: スクレイピングがブラウザセッション内で完結するため、ボット対策は自動でさばかれます。要は、人が手でやっている動きをそのまま自動化しているだけです。
PythonでYouTubeをスクレイピングするのは合法?
何を、どんな手段で取り、そのデータをどう使うか――ここがすべての分かれ目です。
法的な潮目は2024年に変わりました。Meta Platforms v. Bright Data(2024年1月、N.D. Cal.)では、Chen判事が「Metaの利用規約はログイン状態でのスクレイピングのみを禁じており、ログアウト状態の公開データのスクレイピングまでは禁じていない」と判断しました。この判決を境に、公開データのスクレイピングは「かなり低リスク」へと位置づけが移りました。他方で、hiQ v. LinkedIn は、利用規約違反、CFAA違反(偽アカウント使用)、動産妨害が認められ、hiQに50万ドルの判決と恒久差止命令が下りています。
YouTube自身の利用規約は歯切れよく、「ロボット、ボットネット、スクレイパーなどの自動手段でサービスにアクセスすることは禁止」と明記しています。例外は、事前の書面許可がある場合か、適用法で認められる場合のみ。データ取得の正規ルートは、あくまで YouTube Data API です。
実務で押さえておきたい基本線は、こうです。
- 公開データを個人研究や非商用分析のために取るのは、おおむね低リスクです
- API がいちばん安全です。明確に公式の認可を受けています
- 非公開・ログイン必須コンテンツのスクレイピング、著作権動画の再配布目的のダウンロード、コメント由来の個人データで GDPR に抵触する行為は避けてください
- YouTubeコメントには GDPR 第4条(1)にいう個人データが含まれます。EUのデータ主体の情報は慎重に扱いましょう
- 商用スクレイピングは、法務担当への相談をおすすめします
なお、これは法的助言ではありません。状況は目まぐるしく動いています。2025〜2026年には、YouTubeを学習データとして取り込んだAI企業に対し、クリエイター側からDMCA §1201をめぐる訴訟が相次ぎ、業界の空気そのものが変わりつつあります。
PythonでYouTubeをスクレイピングするなら、どの方法を使うべき?
選び方の目安は、次のとおりです。
- 数ページからメタデータをすぐ取りたい? → 方法1(requests + BS4)。速くて軽く、
requestsとbeautifulsoup4以外の依存も最小限です。 - 検索結果を取りたい、動的ページとやり取りしたい? → 方法2(Selenium/Playwright)。完全なブラウザレンダリングと無限スクロール対応が武器ですが、遅く、検知もされやすいです。
- 大量のメタデータ、コメント、字幕が欲しい? → 方法3(yt-dlp)。単体ツールとしての機能の厚みは随一。157K+スター は伊達ではありません。
- そこそこの規模で、構造化された信頼性の高いデータが欲しい? → 方法4(YouTube Data API)。公式でクリーンですが、1日10,000ユニットの縛りがあります。
- コードなしで2分以内にデータが欲しい? → Thunderbit。ブラウザベース、AI搭載、クリックだけでGoogle Sheetsへ流せます。
どれも万能ではありません。上の比較表と取得可能データ表は、次のプロジェクトでもきっと役に立ちます。ほかのウェブスクレイピング手法も覗いてみたい方には、ThunderbitブログにPythonスクレイピング入門からGoogle Sheetsへのデータ抽出まで、いろいろなガイドが揃っています。
YouTubeスクレイピングでThunderbitを試す Get Started Free
FAQ
APIキーなしでYouTubeをスクレイピングできますか?
できます。方法1(requests + BS4)、方法2(Selenium/Playwright)、方法3(yt-dlp)はいずれもAPIキー不要です。APIキーが要るのは方法4(YouTube Data API)だけ。Thunderbit もAPIキーなしで動き、ブラウザ上でそのままスクレイピングします。
PythonでYouTubeを最速でスクレイピングする方法は?
Pythonに限れば、yt-dlp と requests + BS4 が双璧です。どちらもブラウザのオーバーヘッドがなく、動画ごとのメタデータを数秒で取れます。とりわけ yt-dlp はページ送りを内部で処理するので、バッチ処理に強いです。Pythonを使わないなら、セットアップ不要の Thunderbit が総合では最速です。
PythonでYouTubeコメントを取得するには?
いちばん手軽なのは yt-dlp の getcomments オプションです。YouTube Data API でも commentThreads.list で取れます(1回1クオータ、1ページ最大100件)。Selenium/Playwright でもスクロールしてコメント要素を拾えば理屈の上では可能ですが、遅くて壊れやすいのが難点です。
PythonでYouTube Shortsはスクレイピングできますか?
できます。yt-dlp は Shorts のメタデータにもよく対応していて、通常動画に Shorts 固有の項目が足された形で扱えます。YouTube Data API も一部対応します(Shorts の再生回数カウントは2025年4月30日に仕様変更され、いまは再生開始や再視聴もカウント対象です)。BS4 や Selenium/Playwright は、Shorts 棚のDOM構造が通常と異なるため、対応は限られます。
1日に何本のYouTube動画をスクレイピングできますか?
YouTube Data API では、1日およそ10,000クオータユニットが天井です。videos.list をバッチで回せば(1回50IDで1ユニット)、理論上は1日最大50万件の動画統計を引けますが、search.list は1回100ユニットなので予算をすぐ削ります。スクレイピング方式(BS4、Selenium、yt-dlp)の制約は、固定上限というより運用上のものです。プロキシ構成やリクエストパターン次第ですが、IPブロックはおおむね1IPあたり1日数百〜数千リクエストあたりで起きやすくなります。Thunderbit はプランに応じたクレジット制です。
さらに詳しく


