YouTube Transcript API Rate Limit: What It Is and How to Handle 429s

Why APIs return 429 Too Many Requests, what RFC 6585 and the Retry-After header actually specify, how rate limits differ from daily quota, and how to implement correct retry and backoff logic.

00:08:00 · SEP 13, 2026

簡単な回答

429は、プランの1分あたりのリクエスト上限より速くリクエストを送っていることを意味します - クレジットや日次クォータとは無関係です。レスポンスにRetry-Afterヘッダーが含まれている場合は、その時間だけ正確に待ってください。含まれていない場合は、ジッターを加えた指数バックオフを使用し、同時に処理中のリクエスト数の上限も別途設けてください。

レート制限とクォータの違い

これらはよく混同される2つの異なる制約です:

  • クォータ - より長い時間枠(例: 1日)にわたって許可される総リクエスト数。使い切ると、時にはリセットまで何時間も待つ必要があります。
  • レート制限 - より短い時間枠(例: 1分)ごとに許可されるリクエスト数。これに達しても、数秒から数分待つだけで済み、何時間も待つ必要はありません。

内部的には、ほとんどのAPIはトークンバケット(一定のペースでリクエスト「トークン」が蓄積され、リクエストごとに1つ消費する方式で、短時間のバーストを許容する)または固定/スライディングウィンドウカウンター(暦上の1分あたりのハードキャップで、境界でリセットされる方式)のいずれかでレート制限を実装しています。どちらの方式を採用しているかによって、トラフィックがどれだけバースト的であっても安全かが変わります - トークンバケットは固定ウィンドウよりも短時間のスパイクをうまく許容します。

HTTP標準: RFC 6585とRetry-After

429 Too Many Requestsは特定プロバイダー独自の慣習ではなく、標準的なHTTPステータスコードとしてRFC 6585(2012年4月)で正式に定義されています。RFC 9110によれば、準拠したサーバーは429(または503)レスポンスに次の2つの形式のいずれかでRetry-Afterヘッダーを付与してもよいとされています:

  • 秒数指定形式 - 整数、例: Retry-After: 120は120秒待つことを意味します。
  • HTTP日時形式 - 絶対的なタイムスタンプ、例: Retry-After: Wed, 21 Oct 2026 07:28:00 GMT

このヘッダーが存在する場合、それは権威的な情報です - サーバーは次にいつリクエストを受け付けるかを正確に伝えています。その上に独自の指数バックオフを重ねないでください。それは回復をさらに遅らせるだけです。ヘッダーが存在しない場合にのみバックオフにフォールバックしてください。

GetYouTubeTranscriptのレート制限

プランレート制限
無料毎分60リクエスト
月額($5/月)毎分200リクエスト
年額($4.50/月)毎分300リクエスト

実際の適用方法

これはローリングウィンドウやトークンバケットではなく、APIキーごとの固定1分間ウィンドウです - カウンターは時計の分の境界でリセットされます。現時点ではRetry-Afterヘッダーを送信しないため、このAPIからの429はすべて「最大約60秒待ってバックオフしながら再試行する」ものとして扱ってください。存在しないヘッダーを解析しようとするのではなく、下記のコードパターンを使用してください。

429を正しく処理する

正しい処理順序は、まずRetry-Afterを確認し、それが欠落している場合にのみジッター付きの指数バックオフにフォールバックすることです。ジッター(待機時間をわずかにランダム化すること)が重要なのは、多数のクライアントが同時に制限にぶつかり、すべてが同一のスケジュールで再試行すると、それらが同期して即座に同じ制限に再びぶつかる「サンダリングハード」を引き起こすためです。

Node.js:

async function getTranscriptWithRetry(videoId, apiKey, maxRetries = 4) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fetch(
      `https://getyoutubetranscript.com/api/v1/transcript?v=${videoId}`,
      { headers: { Authorization: `Bearer ${apiKey}` } }
    );
    if (res.status !== 429) return res.json();

    const retryAfter = res.headers.get('retry-after');
    const waitMs = retryAfter
      ? Number(retryAfter) * 1000
      : 500 * 2 ** attempt + Math.random() * 250; // exponential backoff + jitter
    await new Promise((r) => setTimeout(r, waitMs));
  }
  throw new Error('Rate limited after retries');
}

Python:

import os, time, random, requests

def get_transcript_with_retry(video_id, api_key, max_retries=4):
    url = "https://getyoutubetranscript.com/api/v1/transcript"
    for attempt in range(max_retries + 1):
        res = requests.get(url, params={"v": video_id}, headers={"Authorization": f"Bearer {api_key}"})
        if res.status_code != 429:
            return res.json()

        retry_after = res.headers.get("Retry-After")
        wait = float(retry_after) if retry_after else (0.5 * 2 ** attempt + random.uniform(0, 0.25))
        time.sleep(wait)
    raise RuntimeError("Rate limited after retries")

レート vs. 並行数 - 別の問題

1分あたりのリクエスト上限と、処理中(in-flight)の並行数の上限は同じものではありません。Promise.allで50個のリクエストを同時に発火させると、その分の合計が予算内に十分収まっていても429にぶつかることがあります。サーバー(またはその手前のプロキシ)が同時接続数も別途制限している場合があるためです。多数の動画をバッチ処理する際は、レート制限のバックオフとは別に、並行数を独立して制限してください:

import pLimit from 'p-limit';

const limit = pLimit(5); // at most 5 requests in flight at once
const results = await Promise.all(
  videoIds.map((id) => limit(() => getTranscriptWithRetry(id, apiKey)))
);

継続的な大量バッチ処理の場合、プランをアップグレードすると毎分あたりのリクエスト上限が直接引き上げられます - APIドキュメントの料金をご覧いただくか、ダッシュボードから100無料クレジットで始めてください。

レート制限に関するよくある質問

Q01

レート制限とクォータの違いは何ですか?

クォータは一定期間(例: 1日)における総使用量の上限です。レート制限は、1日の総使用量とは関係なく、単位時間あたり(例: 1分)に送れるリクエスト数の上限です - 1日のクォータには十分余裕があってもレート制限に達することがあります。クォータ側の詳細については、当社のYouTube APIクォータガイドをご覧ください。

Q02

429レスポンスとはどういう意味ですか?

429 Too Many Requestsは2012年のRFC 6585で正式に定義されました。プランのウィンドウあたりのリクエスト制限を超えたことを意味し、速度を落として再試行すべきというサインであり、リクエストが無効であることやクレジット切れであることを意味するものではありません。

Q03

Retry-Afterヘッダーとは何ですか?常に信頼してよいのですか?

RFC 9110によれば、サーバーは429または503レスポンスに、秒数の整数(Retry-After: 120)または絶対的なHTTP日時のいずれかの形式でRetry-Afterヘッダーを含めてもよいとされています。存在する場合は、独自のバックオフを重ねるのではなく、そのまま従ってください - サーバーが次にいつ再試行すべきかについての権威的な回答を提示しています。

Q04

GetYouTubeTranscriptのレート制限はどうなっていますか?Retry-Afterヘッダーは送信されますか?

無料プランで毎分60リクエスト、月額プランで毎分200リクエスト、年額プランで毎分300リクエストで、APIキーごとの固定1分間ウィンドウ(ローリングウィンドウではない)として適用されます。現時点では429にRetry-Afterヘッダーを付与していないため、それを期待するのではなく独自のバックオフを実装してください(下記のコードを参照)。ウィンドウがローリングではなく固定であるため、待ち時間は最大でも現在の分の残り時間です。

Q05

429によってクレジットは消費されますか?

いいえ - レート制限にかかったリクエストが課金されることはありません。成功したリクエストのみがクレジットを消費します。

Q06

スループットを上げるために複数のAPIキーを取得すべきですか?

いいえ - これは通常プロバイダーの公正利用規約に違反します。GetYouTubeTranscriptでは、レート制限はすでにAPIキーごとに適用されていますが、クレジットとアカウントの状態は、生成したキーの数にかかわらずアカウント単位で追跡されます。より高いスループットが必要な場合は、代わりにプランをアップグレードしてください。これにより毎分あたりのリクエスト上限が直接引き上げられます。

Q07

毎分あたりのリクエスト制限内にもかかわらず、なぜリクエストが失敗するのですか?

これは通常レートの問題ではなく並行数の問題です - 50個のリクエストを並列で発火させると、その分の合計が予算内であってもサーバーに負荷をかけすぎることがあります。並行数リミッター(Node.jsのp-limitやPythonのセマフォなど)を使って、1分あたりに送るリクエスト数とは別に、同時に処理中のリクエスト数を制限してください。

関連記事