TL;DR: youtube-transcript-api のエラーは、原因がそれぞれ違います。AttributeError は古いコード、NoTranscriptFound は言語の指定漏れで、どちらもコードの修正で直ります。IpBlocked と RequestBlocked は実行場所の IP の問題なので、コードを直しても解決しません。プロキシを自分で運用したくない本番環境なら、TranscriptFetch の YouTube Transcript API に取得部分を任せる方法があります。私たちが作っているサービスなので、その点は差し引いて読んでください。
この記事の出力はすべて、2026 年 11 月 7 日に youtube-transcript-api 1.2.5 で実行して確認したものです。実行しなかった部分は、そのように書いています。
エラー別の早見表
| 表示されるエラー | 原因 | 対処 |
|---|---|---|
AttributeError: ... no attribute 'get_transcript' | 古い書き方のコード | YouTubeTranscriptApi().fetch() に書き換える |
NoTranscriptFound (('en',) と表示) | 既定の言語が英語 | languages=['ja'] を指定する |
TranscriptsDisabled | 動画の字幕が無効 | 字幕以外の方法が必要 (音声の文字起こしなど) |
IpBlocked / RequestBlocked | YouTube が IP をブロック | 実行場所を変える、またはプロキシを使う |
TranscriptsDisabled だけは今回再現しておらず、ライブラリのソースにあるメッセージ (Subtitles are disabled for this video) から書いています。
AttributeError: 古い記事のコードが動かない
youtube-transcript-api の使い方を検索すると、次の書き方の記事がまだ多く見つかります。
from youtube_transcript_api import YouTubeTranscriptApi
YouTubeTranscriptApi.get_transcript("VIDEO_ID")1.2.5 で実行すると、こうなります。
AttributeError: type object 'YouTubeTranscriptApi' has no attribute 'get_transcript'list_transcripts も同じです。今の書き方では、インスタンスを作ってから fetch() か list() を呼びます。
from youtube_transcript_api import YouTubeTranscriptApi
api = YouTubeTranscriptApi()
transcript = api.fetch("VIDEO_ID", languages=["ja", "en"])
for snippet in transcript:
print(snippet.text, snippet.start, snippet.duration)
# 辞書のリストが必要なら
rows = transcript.to_raw_data()戻り値の要素は辞書ではなくオブジェクトです。segment["text"] と書いている古いコードは、snippet.text に直すか、to_raw_data() を使ってください。
NoTranscriptFound: 日本語の動画は言語の指定が必須
languages を省略すると、英語の字幕だけを探します。日本語の Python 入門動画 5 本で試したところ、5 本すべてが NoTranscriptFound になりました。
No transcripts were found for any of the requested language codes: ('en',)
For this video (HCZNs3AyFM8) transcripts are available in the following languages:
(MANUALLY CREATED)
None
(GENERATED)
- ja ("Japanese (auto-generated)")[TRANSLATABLE]メッセージの後半に、実際にある字幕の一覧が出ています。languages=["ja"] を付けると、5 本とも取得できました。字幕がない動画と勘違いしやすいので、('en',) の部分を確認してください。
なお、取得できた日本語の字幕は 5 本とも自動生成でした。
日本語の自動字幕で気をつけること
同じ 5 本の字幕を調べました。動画によって、かなり差があります。
| 動画 ID | セグメント数 | 文字数 | 句点 (。) の数 |
|---|---|---|---|
tCMl1AWfhQQ | 2,676 | 48,384 | 0 |
HCZNs3AyFM8 | 1,190 | 20,638 | 814 |
iqNBNzlO_-4 | 3,383 | 61,228 | 1,403 |
HyU3XL2F9GE | 1,461 | 20,409 | 0 |
hv0w4ZCT-uQ | 4,577 | 71,299 | 0 |
後処理を書くときに効いてくるのは、次の 3 点です。
句点がない字幕があります。 5 本のうち 3 本は句点が 0 個でした。句点で文を分割する処理は、これらの動画では動きません。
セグメントは単語の途中で切れます。 実際の出力は
この動画での次がはPYON超入門講座について説明をしでした。英語の感覚でスペースを挟んで連結すると、文の途中に空白が入ります。日本語では"".join(s.text for s in transcript)のように、空文字で連結してください。固有名詞は誤認識されます。 タイトルに「Python超入門」とある動画の字幕では、
Pythonが 27 回、PYONが 42 回でした。検索用のインデックスを作るなら、こうした表記ゆれを見込んでおく必要があります。
翻訳字幕の取得だけ IpBlocked になる場合
自動字幕には [TRANSLATABLE] と表示され、ライブラリには translate() があります。ただ、私たちの環境では次のコードが 2 回とも IpBlocked になりました。
transcript = api.list("HCZNs3AyFM8").find_transcript(["ja"])
english = transcript.translate("en").fetch() # IpBlocked同じネットワークから、通常の fetch() は前後とも成功しています。IP 全体がブロックされたわけではなく、翻訳字幕のリクエストだけが通らなかった形です。試行は 2 回だけなので、常に起きるとは言えません。翻訳が必要なら、日本語の字幕を取得してから、自分で翻訳 API に渡すほうが確実です。
IpBlocked と RequestBlocked: クラウドでだけ動かない
ローカルでは動くのに、デプロイすると失敗する場合はこのエラーです。ライブラリのメッセージには、原因が 2 つ挙げられています。
YouTube is blocking requests from your IP. This usually is due to one of the following reasons:
- You have done too many requests and your IP has been blocked by YouTube
- You are doing requests from an IP belonging to a cloud provider (like AWS, Google Cloud Platform, Azure, etc.). Unfortunately, most IPs from cloud providers are blocked by YouTube.つまり、リクエストのしすぎか、クラウド事業者の IP かのどちらかです。コードの問題ではないので、リトライを増やしても、同じ IP のままでは解決しないことがほとんどです。
対処は次の順に検討してください。
- リクエストの間隔を空ける。 大量に取得しているなら、まずここからです。
- 実行場所を変える。 自宅や社内の回線で動くなら、取得だけをそちらで行う方法があります。
- 住宅用プロキシを使う。 ライブラリにはプロキシの設定があります。
from youtube_transcript_api import YouTubeTranscriptApi
from youtube_transcript_api.proxies import GenericProxyConfig
api = YouTubeTranscriptApi(
proxy_config=GenericProxyConfig(
http_url="http://user:[email protected]:80",
https_url="http://user:[email protected]:80",
)
)このコードはクラスの引数までを確認したもので、実際のプロキシ経由では実行していません。
住宅用プロキシも万能ではない
ライブラリのメッセージによれば、プロキシを使っても、そのプロキシの IP がブロックされない保証はありません。Webshare の無料枠は「Proxy Server」のプランなので動かない、とも書かれています。
私たちは本番で YouTube へのリクエストを住宅用プロキシ経由で送っており、2026 年 9 月に 2 社を同じ条件で比較しました。各社 400 の出口 IP から、同じ動画にリクエストした結果です。
| プロバイダ A | プロバイダ B | |
|---|---|---|
| 試した出口 IP | 400 | 400 |
| YouTube にブロックされた | 20.5% | 4.5% |
| 接続できなかった | 13.3% | 0% |
| 使えた出口 IP | 66% | 95.5% |
「住宅用」でも、A 社では 5 個に 1 個の IP が最初からブロックされていました。プロキシを試すときは、ブロックされた IP を入れ替えてリトライする処理まで含めて考える必要があります。
プロキシを運用したくない場合
ここまでの作業を自分で持ちたくない場合、ホスト型の API に任せる方法があります。TranscriptFetch の YouTube Transcript API はその一つで、動画の ID か URL を送ると、字幕を JSON で返します。IP のブロックやプロキシはこちら側で処理します。
from transcriptfetch import TranscriptFetch
client = TranscriptFetch(api_key="YOUR_API_KEY")
resp = client.transcripts.video("HCZNs3AyFM8")
text = "".join(s.text for s in resp.segments)
print(resp.language, text[:40])curl https://transcriptfetch.com/api/v2/transcripts/video \
-H "Authorization: Bearer $TRANSCRIPTFETCH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"video":"HCZNs3AyFM8"}'HCZNs3AyFM8 をキーなしのトライアル (/mcp/try) で試すと、言語の指定なしで language が ja、source が captions で返りました。
正直に書いておくと、良くない点もあります。
textフィールドにはスペースが入ります。 現在は、セグメントの境目に半角スペースが入ります。日本語では上のコードのように、segmentsを空文字で連結してください。サービスは英語です。 ドキュメントも管理画面も英語で、料金は米ドルです。
API キーが必要です。 無料のアカウントには 50 クレジットが付きます。カードは不要ですが、更新はされません。その後は月 5 ドルで 1,000 クレジットです。失敗したリクエストは課金されません。
字幕がない動画では音声から文字起こしをします。こちらは音声 5 分ごと (端数は切り上げ) に 1 クレジットです。字幕だけでよければ mode="captions" を指定してください。試す場合は無料アカウントを作成できます。
よくある質問
FAQ
現在の youtube-transcript-api では get_transcript と list_transcripts がなくなったためです。バージョン 1.2.5 で実行すると、どちらも AttributeError になりました。YouTubeTranscriptApi() でインスタンスを作り、fetch() と list() を使ってください。
fetch() の既定の言語が英語 (en) だからです。試した日本語の動画 5 本はすべて、languages を指定しないと NoTranscriptFound になり、languages=['ja'] を付けると取得できました。
いいえ。ライブラリのメッセージは、リクエストのしすぎとクラウド事業者の IP の 2 つを主な原因に挙げています。私たちの環境では、通常の字幕取得が成功している同じネットワークで、translate() を使った翻訳字幕の取得だけが 2 回とも IpBlocked になりました。
動画によります。試した 5 本のうち、句点が付いていたのは 2 本で、残りの 3 本は句点が 0 個でした。要約や検索に使うなら、句読点がない場合も想定しておくと安全です。
