これまでに requests.get("https://www.youtube.com/...") を投げて、BeautifulSoupで動画タイトルを拾おうとしてみたことがあるなら、もう結末は想像がつくはずです。返ってくるのは空っぽの <div> だらけのHTMLで、使えるデータはゼロ。ほんと、拍子抜けです。
YouTubeを初めてスクレイピングしようとする開発者が、ほぼ必ずぶつかるのがこの問題です。YouTubeはシングルページアプリケーションで、ほとんどの内容をJavaScriptでクライアント側に描画します。Pythonスクリプトが受け取るHTMLは、いわば外側の殻だけ。本当の動画タイトル、再生回数、メタデータはどうなっているかというと、ytInitialData という巨大なJSONの塊に入っていて、ページ読み込み後にJSによって差し込まれます。
だから、いかにも正しそうな soup.find("div", class_="ytd-video-renderer") は None を返します。というのも、その要素は生のHTTPレスポンスには最初から存在していないからです。この仕組みを理解した瞬間、点と点がつながりました。そして、ここで紹介する4つの方法は、数え切れないほど試行錯誤して壊しては直し、GitHubのissueを読み漁った末にたどり着いたものです。各手法の使いどころをきちんと整理しつつ、最後には「環境構築なしで、とにかくデータだけ欲しい」という人向けにノーコードの近道も紹介します。
そもそも、なぜPythonでYouTubeをスクレイピングするのか?
YouTubeは単なる動画サイトではありません。実はを抱える、巨大なデータソースです。があり、しかもされているので、企業、研究者、クリエイターがプログラムで分析したい公開情報が山ほどあります。
ただし、YouTubeの標準分析機能で見られるのは自分のチャンネルのデータだけです。競合の投稿頻度を把握したい、自分の業界で伸びている話題を追いたい、他人の動画コメントから視聴者の反応を分析したい、そんなときはスクレイピングが必要になります。
実際によくあるユースケースは、たとえば次のようなものです。
| 用途 | 必要とする人 | 対象データ |
|---|---|---|
| 競合分析 | マーケティングチーム、コンテンツ戦略担当 | 再生回数、投稿頻度、エンゲージメント率 |
| リード獲得 | 営業チーム、B2B営業 | チャンネルの連絡先情報、説明欄のビジネスメール |
| 市場調査 | プロダクトマネージャー、アナリスト | トレンドトピック、コメントから見える視聴者の反応 |
| コンテンツ戦略 | YouTuber、代理店 | 伸びているフォーマット、効果的なタイトル・タグの傾向 |
| SEO / キーワード調査 | SEO担当者 | 動画タイトル、タグ、説明文、ランキングシグナル |
| ブランドモニタリング | PRチーム、ブランド担当 | 動画タイトル、コメント、説明文に出る自社名言及 |
| 学術研究 | 研究者、データサイエンティスト | 感情分析 用のコメントデータセット(ある2025年の研究では、45K件のYouTubeコメントでBERTをファインチューニングし、93.1%の精度を達成) |
たとえばDJI、GoPro、Insta360を比較した競合分析では、という結果が出ています。こうした洞察は、YouTube Studioの中だけを見ていても見えてきません。
なぜ requests + BeautifulSoup だけではYouTubeをスクレイピングできないのか
実際の手法に入る前に、なぜ王道のやり方が失敗するのかを理解しておきましょう。これは学術的な話ではなく、デバッグ時間を何時間も節約してくれます。
「普通にやる」と、概念的にはこんな感じになります。
1import requests
2from bs4 import BeautifulSoup
3response = requests.get("https://www.youtube.com/@somechannel/videos")
4soup = BeautifulSoup(response.text, "html.parser")
5videos = soup.find_all("a", id="video-title-link")
6print(len(videos)) # 0 — 毎回こうなる
結果はいつもゼロです。にもある通り、「ページが動的に読み込まれているため、requestsでは対応できない」のです。はさらに率直で、「requests と BeautifulSoup だけではJavaScriptは実行できない」と説明しています。
では仕組みがこう説明されています。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 だと即ブロックされます。でも、初心者が最もやりがちな落とし穴だとされています。
1import requests
2HEADERS = {
3 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
4 "AppleWebKit/537.36 (KHTML, like Gecko) "
5 "Chrome/114.0.0.0 Safari/537.36",
6 "Accept-Language": "en-US,en;q=0.9",
7 "Cookie": "CONSENT=YES+cb", # EUの同意壁を回避
8}
9url = "https://www.youtube.com/@mkbhd/videos"
10response = requests.get(url, headers=HEADERS)
11print(response.status_code) # 200 のはず
CONSENT Cookie は重要です。これがないと、EU地域からのリクエストは consent.youtube.com にリダイレクトされ、ytInitialData が一切含まれていないHTMLが返ってきます。
手順2: HTMLを解析して ytInitialData スクリプトを見つける
BeautifulSoup か正規表現で、var ytInitialData = を含む <script> タグを探します。
1import re
2import json
3# ytInitialData JSON を抽出
4match = re.search(
5 r"var ytInitialData\s*=\s*({.*?});</script>",
6 response.text,
7 re.DOTALL
8)
9if match:
10 data = json.loads(match.group(1))
11 print("ytInitialData の抽出に成功しました")
12else:
13 print("ytInitialData が見つかりません。ヘッダーやCookieを確認してください")
よくあるミスは、終端を }; だけにした非貪欲 .*? を使うことです。JSONの中には入れ子の終端が何度も出てくるため、そこで途中終了してしまいます。がやっているように、};</script> を終端に使うのが安全です。これはそのスクリプトブロック内で最後の代入だからです。
手順3: JSON構造をたどって動画データを取り出す
JSONはかなり深くネストされています。YouTubeが構造を少しでも組み替えるたびに壊れる固定パスをハードコードするより、再帰的にキーを探す方がずっと堅牢です(YouTubeの構造変更は頻繁で、でも2023年以降の変更がいくつも記録されています)。
1def search_dict(partial, search_key):
2 stack = [partial]
3 while stack:
4 cur = stack.pop()
5 if isinstance(cur, dict):
6 for k, v in cur.items():
7 if k == search_key:
8 yield v
9 else:
10 stack.append(v)
11 elif isinstance(cur, list):
12 stack.extend(cur)
13# チャンネルページから動画情報を抽出
14videos = []
15for vr in search_dict(data, "videoRenderer"):
16 videos.append({
17 "video_id": vr.get("videoId"),
18 "title": vr["title"]["runs"][0]["text"],
19 "views": vr.get("viewCountText", {}).get("simpleText", "N/A"),
20 "published": vr.get("publishedTimeText", {}).get("simpleText", "N/A"),
21 })
22print(f"{len(videos)}本の動画を見つけました")
23for v in videos[:5]:
24 print(f" {v['title']} — {v['views']}")
この再帰的な方法は、、yt-dlp、Scrapfly が最終的にたどり着いたやり方でもあります。YouTubeの頻繁なJSON再編成に耐えやすいのが強みです。
手順4: 取得したデータをCSVやExcelに書き出す
1import csv
2with open("youtube_videos.csv", "w", newline="", encoding="utf-8") as f:
3 writer = csv.DictWriter(f, fieldnames=["video_id", "title", "views", "published"])
4 writer.writeheader()
5 writer.writerows(videos)
6print("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をおすすめします。では、PlaywrightはSeleniumに比べてとされています。PlaywrightはChrome DevTools Protocolを使った持続的なWebSocket通信を行い、SeleniumはWebDriver over HTTPで1コマンドごとに変換層が入ります。
手順1: Playwright をセットアップする
1pip install playwright
2playwright install chromium
1from playwright.sync_api import sync_playwright
2pw = sync_playwright().start()
3browser = pw.chromium.launch(headless=False) # 表示ありの方が検知されにくい
4context = browser.new_context()
5# EUの同意壁を回避するためにCookieを事前設定
6context.add_cookies([{
7 "name": "SOCS",
8 "value": "CAISNQgDEitib3FfaWRlbnRpdHlmcm9udGVuZHVpc2VydmVyXzIwMjMwODI5LjA3X3AxGgJlbiACGgYIgJnPpwY",
9 "domain": ".youtube.com",
10 "path": "/",
11}])
12page = context.new_page()
手順2: YouTubeページを開いて読み込み完了を待つ
1page.goto("https://www.youtube.com/@mkbhd/videos")
2page.wait_for_selector("a#video-title-link", timeout=15000)
3print("ページが読み込まれ、動画要素が表示されました")
検索結果を取る場合は、https://www.youtube.com/results?search_query=your+query にアクセスします。
手順3: 無限スクロールでさらに動画を読み込む
YouTubeのチャンネルページや検索結果は無限スクロールです。以下は、をもとにした定番の scrollHeight ループです。
1prev_height = -1
2max_scrolls = 20 # ここで上限を設ける。1万本のチャンネルを延々スクロールし続けないため
3scroll_count = 0
4while scroll_count < max_scrolls:
5 page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
6 page.wait_for_timeout(1500) # 新しいコンテンツが読み込まれるのを待つ
7 new_height = page.evaluate("document.body.scrollHeight")
8 if new_height == prev_height:
9 break # 新しいコンテンツが増えていない
10 prev_height = new_height
11 scroll_count += 1
12print(f"{scroll_count}回スクロールしました")
手順4: レンダリング済みページから動画データを抜き出す
1video_elements = page.query_selector_all("a#video-title-link")
2videos = []
3for el in video_elements:
4 title = el.inner_text()
5 href = el.get_attribute("href")
6 video_id = href.split("v=")[-1] if href else None
7 videos.append({"title": title, "video_id": video_id, "url": f"https://www.youtube.com{href}"})
8print(f"{len(videos)}本の動画を抽出しました")
再生回数や投稿日を取りたい場合は、隣接する要素も拾う必要があります。によると、id="video-title-link" は万能ではなく、YouTubeは複数のページ変種を出しています。より堅牢なフォールバックは a[href*="watch"] です。
手順5: CSV や Google Sheets に書き出す
1import csv
2with open("youtube_playwright.csv", "w", newline="", encoding="utf-8") as f:
3 writer = csv.DictWriter(f, fieldnames=["title", "video_id", "url"])
4 writer.writeheader()
5 writer.writerows(videos)
6browser.close()
7pw.stop()
この方法を使うべき場面、使わない方がいい場面
向いているケース: 検索結果のスクレイピング、動的なページ要素とのやり取り(タブのクリック、説明文の展開)、完全にレンダリングされたDOMが必要な場合。
制限: 遅いです(スクロールして抽出する流れだと、1本あたり約1.5〜3秒)。ボット検知リスクも高めで、素のSeleniumは navigator.webdriver === true を設定するため、。さらにリソース消費も大きく、ブラウザインスタンス1つで200〜500MBのRAMを使います。100本なら、yt-dlpなら数秒のところが、3〜8分かかることもあります。
方法3: yt-dlp を使って YouTube をスクレイピングする
yt-dlp は、YouTubeスクレイピング界のスイスアーミーナイフです。youtube-dl のコミュニティフォークで、、夜間ビルドも活発、メタデータ、コメント、字幕、バッチ処理まで標準対応。しかもブラウザもAPIキーも不要です。
- 難易度: 初級〜中級
- 所要時間: 約10分
- 必要なもの: Python 3.10以上、
pip install yt-dlp
手順1: yt-dlp をインストールする
1pip install yt-dlp
ブラウザドライバも、APIキーも、設定ファイルもいりません。
手順2: ダウンロードせずに動画メタデータを取得する
1import yt_dlp
2opts = {
3 "quiet": True,
4 "skip_download": True, # 動画本体は取らず、メタデータだけ
5 "no_warnings": True,
6}
7with yt_dlp.YoutubeDL(opts) as ydl:
8 info = ydl.extract_info(
9 "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
10 download=False
11 )
12print(f"タイトル: {info['title']}")
13print(f"再生回数: {info['view_count']:,}")
14print(f"高評価数: {info.get('like_count', 'N/A')}")
15print(f"長さ: {info['duration']}秒")
16print(f"投稿日: {info['upload_date']}")
17print(f"チャンネル: {info['channel']} ({info.get('channel_follower_count', 'N/A')} 登録者)")
18print(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動画のコメントを取得する
1opts = {
2 "quiet": True,
3 "skip_download": True,
4 "getcomments": True,
5 "extractor_args": {
6 "youtube": {
7 "max_comments": ["200", "50", "50", "10"], # total, parents, replies-per, replies-total
8 "comment_sort": ["top"],
9 }
10 },
11}
12with yt_dlp.YoutubeDL(opts) as ydl:
13 info = ydl.extract_info(
14 "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
15 download=False
16 )
17comments = info.get("comments", [])
18print(f"{len(comments)}件のコメントを取得しました")
19for c in comments[:3]:
20 print(f" [{c.get('like_count', 0)} likes] {c['author']}: {c['text'][:80]}...")
コメント取得は遅いです。では、コメント取得速度が約30KB/sと報告されており、コメント10万件の動画だと何時間もかかることがあります。 では、コメントのページ送りが終わる前にフォーマットURLが失効する(約6時間)ケースも記録されています。大きい動画では max_comments を強めに絞りましょう。
手順4: トランスクリプトと字幕を取得する
YouTube Data API でもBS4でも、完全なトランスクリプトは取れません。ここはyt-dlpの独壇場です。
1opts = {
2 "quiet": True,
3 "skip_download": True,
4 "writesubtitles": True,
5 "writeautomaticsub": True,
6 "subtitleslangs": ["en", "en-orig"],
7 "subtitlesformat": "json3", # 機械処理しやすい: start/dur(ms)+ text
8 "outtmpl": "%(id)s.%(ext)s",
9}
10with yt_dlp.YoutubeDL(opts) as ydl:
11 info = ydl.extract_info(
12 "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
13 download=False
14 )
15# 字幕データは info 辞書から直接参照できる
16auto_captions = info.get("automatic_captions", {})
17manual_subs = info.get("subtitles", {})
18print(f"自動字幕の言語: {list(auto_captions.keys())[:10]}")
19print(f"手動字幕の言語: {list(manual_subs.keys())}")
機械処理には json3 形式が便利です。各セグメントに start / dur がミリ秒単位で入り、テキストも含まれます。言語コードは BCP-47 形式です(en、en-US、zh-Hans、ja、es など)。
手順5: 複数動画やチャンネル全体をまとめてスクレイピングする
1opts = {
2 "quiet": True,
3 "skip_download": True,
4 "extract_flat": "in_playlist", # 高速。動画IDとタイトルだけ取得
5 "sleep_interval": 2,
6 "max_sleep_interval": 6,
7}
8with yt_dlp.YoutubeDL(opts) as ydl:
9 info = ydl.extract_info(
10 "https://www.youtube.com/@mkbhd/videos",
11 download=False
12 )
13entries = info.get("entries", [])
14print(f"チャンネル内で{len(entries)}本の動画を見つけました")
15for e in entries[:5]:
16 print(f" {e.get('title', 'N/A')} — {e.get('id')}")
チャンネルURL、プレイリストURL、あるいは検索クエリ(ytsearch10:python scraping)を渡せば、yt-dlpが内部でページ送りを処理してくれます。
この方法を使うべき場面、使わない方がいい場面
向いているケース: 大量のメタデータ抽出、コメント、字幕、動画ダウンロード、チャンネル全体の取得など、必要な項目が多い場合。
制限: 検索結果ページのスクレイピングにはあまり向きません(そこはSelenium/Playwrightの方が得意です)。2024〜2026年のボット対策強化で、yt-dlpを大規模運用する難易度は上がっています。YouTubeは一部クライアントに対してを要求するようになりました。本番用途では、 プラグインを入れ、--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 キーを取得する
- にアクセス
- 新しいプロジェクトを作成、または既存のものを選択
- API とサービス → ライブラリ に進み、「YouTube Data API v3」を検索して 有効化
- API とサービス → 認証情報 → 認証情報を作成 → APIキー
- キーをコピーし、下のコードで使います
手順2: 最初のAPI呼び出しを行う
1from googleapiclient.discovery import build
2API_KEY = "YOUR_API_KEY_HERE"
3youtube = build("youtube", "v3", developerKey=API_KEY)
4# 特定動画の詳細を取得
5response = youtube.videos().list(
6 part="snippet,statistics,contentDetails",
7 id="dQw4w9WgXcQ"
8).execute()
9video = response["items"][0]
10print(f"タイトル: {video['snippet']['title']}")
11print(f"再生回数: {video['statistics']['viewCount']}")
12print(f"高評価数: {video['statistics'].get('likeCount', '非表示')}")
13print(f"コメント数: {video['statistics'].get('commentCount', '無効')}")
14print(f"長さ: {video['contentDetails']['duration']}")
15print(f"タグ: {video['snippet'].get('tags', [])[:5]}")
レスポンスは整理されていて型も明確、しかもドキュメント付き。JSONを掘り起こす必要はありません。
手順3: 動画詳細、チャンネル情報、コメントを取得する
1# 動画を検索
2search_response = youtube.search().list(
3 part="snippet",
4 q="python web scraping tutorial",
5 type="video",
6 maxResults=10,
7 order="viewCount"
8).execute()
9for item in search_response["items"]:
10 print(f" {item['snippet']['title']} — {item['id']['videoId']}")
11# コメントを取得
12comments_response = youtube.commentThreads().list(
13 part="snippet",
14 videoId="dQw4w9WgXcQ",
15 maxResults=20,
16 order="relevance"
17).execute()
18for item in comments_response["items"]:
19 comment = item["snippet"]["topLevelComment"]["snippet"]
20 print(f" [{comment['likeCount']} likes] {comment['authorDisplayName']}: {comment['textDisplay'][:80]}")
YouTube API のクオータ事情(ここが重要)
ここが、単なるコピペ記事と本当に役立つガイドの分かれ目です。標準の割り当てはで、太平洋時間の深夜にリセットされます。各API呼び出しのコストは次の通りです。
| 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データが欲しいだけならどうでしょう。たとえば競合分析をしたいマーケターや、プロジェクト環境を作らずにサクッとデータを抜きたい開発者なら、もっと早い方法があります。
は、わざわざコードを書くほどでもない場面のために作ったAIウェブスクレイパーのChrome拡張です。YouTubeページ上でそのまま動きます。
Thunderbit で YouTube を3ステップでスクレイピングする方法
手順1: をインストールし、YouTubeのチャンネルページ、検索結果ページ、または動画ページを開きます。
手順2: サイドバーの 「AIで項目を提案」 をクリックします。AIがページを読み取り、動画タイトル、再生回数、投稿日、長さ、チャンネル名、サムネイルURLなどの列を提案します。必要に応じて列の追加・削除・名称変更もできます。
手順3: 「スクレイピング」 をクリックし、Google Sheets、Excel、CSV、Airtable、Notion にエクスポートします。きれいな表としてすぐ使える形でデータが出力されます。
こんな人に向いています
- 競合チャンネルのデータが欲しいが、コードを書かないマーケター
- 仮想環境の準備や依存関係のインストールをせずに、すぐデータを取りたい開発者
- ボット対策に弾かれている人 — Thunderbit はユーザー自身のログイン済みブラウザセッション内でスクレイピングするため、CookieやPO Tokenを引き継げます。これにより、サーバー側スクレイパーを悩ませるブロックの多くを回避できます
- Thunderbit は も使えるので、各動画ページを開いて、いいね数、説明文、タグなどを表に追加できます
Thunderbit がYouTubeをどう扱うのか、もっと詳しく知りたい方は、 と もぜひご覧ください。
PythonでYouTubeをスクレイピングしてブロックされないためのコツ
以下のポイントは、4つのPython手法すべてに共通します。YouTubeのボット対策はとされており、主なシグナルは3つです。IPの行動分析、JS実行の必要性、そして頻繁に変わるHTML構造です。
すべての手法に共通:
- User-Agent だけでなくヘッダー全体をローテーションする —
Accept、Accept-Language、Sec-CH-UAなどのクライアントヒントも、宣言したUAと整合させる必要があります。 に最新リストがあります。 - リクエスト間に2〜8秒のランダム遅延を入れる。固定間隔は検知シグナルになります。
- 数ページ以上の取得では住宅用プロキシを使う。データセンターIP(AWS、GCP、Hetznerなど)は、です。
- セッションとIPはセットでローテーションする — YouTubeはセッションをIPに紐づけるため、同じCookieが別IPから見えるのは危険信号です。
requests + BS4 の場合: CONSENT=YES+cb Cookie を設定してください。これがないと、EUからのリクエストは同意ページに飛ばされ、データが取れません。
Selenium/Playwright の場合: Linuxサーバーでは --headless=new より、xvfb を使った表示あり実行の方が無難です。ヘッドレスChromeは、精巧な検知にはまだ十分なフィンガープリントを漏らします。 のような、約17種類の回避策を当てるツールも検討できます。
yt-dlp の場合: sleep_interval と max_sleep_interval を使ってください。 プラグインを入れてPO Tokenを生成し、--cookies-from-browser chrome は捨てアカウントで使いましょう。
API の場合: でクオータ使用量を監視し、リクエストをまとめて効率化してください。videos.list は、50個のIDをカンマ区切りで一度に送っても1ユニットです。活用しない手はありません。
Thunderbit の場合: スクレイピングはブラウザセッション内で行われるため、ボット対策は自動で処理されます。要するに、手作業でやることを自動化しているだけです。
PythonでYouTubeをスクレイピングするのは合法?
何を、どうやってスクレイピングするのか、そしてそのデータをどう使うのかによります。
法的な状況は2024年に動きました。Meta Platforms v. Bright Data(2024年1月、N.D. Cal.)では、しました。この判決以降、公開データのスクレイピングは「かなり低リスク」になりました。一方で、hiQ v. LinkedIn は、利用規約違反、CFAA違反(偽アカウント使用)、動産妨害により、が下り、恒久差止命令も出ています。
YouTube自身のは明確です。「ロボット、ボットネット、スクレイパーなどの自動手段でサービスにアクセスすることは禁止」されています。例外は、事前の書面許可がある場合、または適用法で認められる場合です。データ取得の公式ルートは YouTube Data API です。
実務上の基本ルールは次のとおりです。
- 公開データを個人研究や非商用分析のためにスクレイピングするのは、一般にリスクが低めです
- API が最も安全です。明確に公式認可されています
- 非公開・ログイン必須コンテンツのスクレイピング、著作権動画の再配布目的のダウンロード、コメント由来の個人データで GDPR に違反する行為は避けてください
- YouTubeコメントには GDPR 第4条(1)における個人データが含まれます。EUのデータ主体の情報は慎重に扱いましょう
- 商用スクレイピングは法務担当への相談をおすすめします
これは法的助言ではありません。状況は急速に変わっています。2025〜2026年には、YouTubeを学習データとしてスクレイピングしたAI企業に対して、クリエイター側からが相次ぎ、業界全体の空気も変わりつつあります。
PythonでYouTubeをスクレイピングするなら、どの方法を使うべき?
判断の目安は次の通りです。
- 数ページからすぐにメタデータを取りたい? → 方法1(requests + BS4)。高速・軽量で、
requestsとbeautifulsoup4以外の依存も最小です。 - 検索結果を取りたい、動的ページとやり取りしたい? → 方法2(Selenium/Playwright)。完全なブラウザレンダリングと無限スクロール対応が強みですが、遅く、検知されやすいです。
- 大量のメタデータ、コメント、字幕が欲しい? → 方法3(yt-dlp)。単体ツールとして最も高機能です。 には理由があります。
- そこそこの規模で、構造化された信頼性の高いデータが欲しい? → 方法4(YouTube Data API)。公式でクリーンですが、の制限があります。
- コードなしで2分以内にデータが欲しい? → 。ブラウザベース、AI搭載、クリックだけでGoogle Sheetsに出力できます。
どの方法も万能ではありません。上の比較表と取得可能データ表は、次回のプロジェクトでもきっと役立ちます。さらに他のも見てみたい方は、Thunderbitブログにからまで、さまざまなガイドがあります。
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 の再生回数カウントはされ、現在は再生開始や再視聴もカウントされます)。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 はに紐づくクレジット制です。
さらに詳しく
