Back to blog

youtube-transcript-api が動かない原因と対処法: エラー別に実機で検証

youtube-transcript-api の AttributeError、NoTranscriptFound、IpBlocked、RequestBlocked の原因と直し方を、バージョン 1.2.5 と日本語の動画 5 本で実際に試してまとめました。古い記事のコードが動かない理由もわかります。

TL;DR: youtube-transcript-api のエラーは、原因がそれぞれ違います。AttributeError は古いコード、NoTranscriptFound は言語の指定漏れで、どちらもコードの修正で直ります。IpBlocked と RequestBlocked は実行場所の IP の問題なので、コードを直しても解決しません。プロキシを自分で運用したくない本番環境なら、TranscriptFetch の YouTube Transcript API に取得部分を任せる方法があります。私たちが作っているサービスなので、その点は差し引いて読んでください。

この記事の出力はすべて、2026 年 11 月 7 日に youtube-transcript-api 1.2.5 で実行して確認したものです。実行しなかった部分は、そのように書いています。

Guide

エラー別の早見表

表示されるエラー原因対処
AttributeError: ... no attribute 'get_transcript'古い書き方のコードYouTubeTranscriptApi().fetch() に書き換える
NoTranscriptFound (('en',) と表示)既定の言語が英語languages=['ja'] を指定する
TranscriptsDisabled動画の字幕が無効字幕以外の方法が必要 (音声の文字起こしなど)
IpBlocked / RequestBlockedYouTube が IP をブロック実行場所を変える、またはプロキシを使う

TranscriptsDisabled だけは今回再現しておらず、ライブラリのソースにあるメッセージ (Subtitles are disabled for this video) から書いています。

Troubleshooting

AttributeError: 古い記事のコードが動かない

youtube-transcript-api の使い方を検索すると、次の書き方の記事がまだ多く見つかります。

python
from youtube_transcript_api import YouTubeTranscriptApi

YouTubeTranscriptApi.get_transcript("VIDEO_ID")

1.2.5 で実行すると、こうなります。

text
AttributeError: type object 'YouTubeTranscriptApi' has no attribute 'get_transcript'

list_transcripts も同じです。今の書き方では、インスタンスを作ってから fetch() か list() を呼びます。

python
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() を使ってください。

Guide

NoTranscriptFound: 日本語の動画は言語の指定が必須

languages を省略すると、英語の字幕だけを探します。日本語の Python 入門動画 5 本で試したところ、5 本すべてが NoTranscriptFound になりました。

text
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 本とも自動生成でした。

Guide

日本語の自動字幕で気をつけること

同じ 5 本の字幕を調べました。動画によって、かなり差があります。

動画 IDセグメント数文字数句点 (。) の数
tCMl1AWfhQQ2,67648,3840
HCZNs3AyFM81,19020,638814
iqNBNzlO_-43,38361,2281,403
HyU3XL2F9GE1,46120,4090
hv0w4ZCT-uQ4,57771,2990

後処理を書くときに効いてくるのは、次の 3 点です。

  • 句点がない字幕があります。 5 本のうち 3 本は句点が 0 個でした。句点で文を分割する処理は、これらの動画では動きません。

  • セグメントは単語の途中で切れます。 実際の出力は この動画で の次が はPYON超入門講座について説明をし でした。英語の感覚でスペースを挟んで連結すると、文の途中に空白が入ります。日本語では "".join(s.text for s in transcript) のように、空文字で連結してください。

  • 固有名詞は誤認識されます。 タイトルに「Python超入門」とある動画の字幕では、Python が 27 回、PYON が 42 回でした。検索用のインデックスを作るなら、こうした表記ゆれを見込んでおく必要があります。

Troubleshooting

翻訳字幕の取得だけ IpBlocked になる場合

自動字幕には [TRANSLATABLE] と表示され、ライブラリには translate() があります。ただ、私たちの環境では次のコードが 2 回とも IpBlocked になりました。

python
transcript = api.list("HCZNs3AyFM8").find_transcript(["ja"])
english = transcript.translate("en").fetch()  # IpBlocked

同じネットワークから、通常の fetch() は前後とも成功しています。IP 全体がブロックされたわけではなく、翻訳字幕のリクエストだけが通らなかった形です。試行は 2 回だけなので、常に起きるとは言えません。翻訳が必要なら、日本語の字幕を取得してから、自分で翻訳 API に渡すほうが確実です。

Troubleshooting

IpBlocked と RequestBlocked: クラウドでだけ動かない

ローカルでは動くのに、デプロイすると失敗する場合はこのエラーです。ライブラリのメッセージには、原因が 2 つ挙げられています。

text
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 のままでは解決しないことがほとんどです。

対処は次の順に検討してください。

  1. リクエストの間隔を空ける。 大量に取得しているなら、まずここからです。
  2. 実行場所を変える。 自宅や社内の回線で動くなら、取得だけをそちらで行う方法があります。
  3. 住宅用プロキシを使う。 ライブラリにはプロキシの設定があります。
python
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",
    )
)

このコードはクラスの引数までを確認したもので、実際のプロキシ経由では実行していません。

Guide

住宅用プロキシも万能ではない

ライブラリのメッセージによれば、プロキシを使っても、そのプロキシの IP がブロックされない保証はありません。Webshare の無料枠は「Proxy Server」のプランなので動かない、とも書かれています。

私たちは本番で YouTube へのリクエストを住宅用プロキシ経由で送っており、2026 年 9 月に 2 社を同じ条件で比較しました。各社 400 の出口 IP から、同じ動画にリクエストした結果です。

プロバイダ Aプロバイダ B
試した出口 IP400400
YouTube にブロックされた20.5%4.5%
接続できなかった13.3%0%
使えた出口 IP66%95.5%

「住宅用」でも、A 社では 5 個に 1 個の IP が最初からブロックされていました。プロキシを試すときは、ブロックされた IP を入れ替えてリトライする処理まで含めて考える必要があります。

Guide

プロキシを運用したくない場合

ここまでの作業を自分で持ちたくない場合、ホスト型の API に任せる方法があります。TranscriptFetch の YouTube Transcript API はその一つで、動画の ID か URL を送ると、字幕を JSON で返します。IP のブロックやプロキシはこちら側で処理します。

python
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])
bash
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" を指定してください。試す場合は無料アカウントを作成できます。

Guide

よくある質問

FAQ

現在の youtube-transcript-api では get_transcript と list_transcripts がなくなったためです。バージョン 1.2.5 で実行すると、どちらも AttributeError になりました。YouTubeTranscriptApi() でインスタンスを作り、fetch() と list() を使ってください。