Twitter (X) API レート制限ガイド — 15分上限・429 エラー・回避パターン

Akira Watanabe 著•13 分で読了

Twitter (X) API を本番運用すると、ほぼ全てのチームが 429 Too Many Requests に一度はぶつかります。原因は単純に "呼びすぎ" だけではなく、15分単位の per-endpoint cap、ユーザー文脈とアプリ文脈の cap の違い、従量課金の月間上限 (投稿読み取り 300 万件)、そして 2026年に X が pay-per-use モデルへ移行した後に新設された spending limits など、複数のレイヤーが絡みます。

本記事では docs.x.com の公式仕様 (2026 年確認) を基準に、Twitter (X) API のレート制限を endpoint 別の数字 + 失敗時の挙動 + 回避パターン の3層で整理します。さらに、第三者 API である TwitterAPI.io が 15分単位の cap を持たず、代わりに秒単位のレート制限 (初回入金前 0.2 リクエスト/秒、入金後 20 リクエスト/秒) と従量課金というシンプルな設計を採っている理由と、両者をどう使い分けるかをまとめます。

実装例は Python (requests + token-bucket リミッター)。コピペで動く形で、429 を捕捉して exponential backoff + jitter を入れる典型パターンを書いています。

01 — Section

そもそも "レート制限" とは何を指すのか

Twitter (X) API でいう "レート制限" は実は 2 軸 × 2 軸 = 4 種類 あります。これを混同するとレート制限の挙動が予測できなくなります。

軸 A: 集計窓 — 15分窓 (短期 burst 制限) と 月単位 (使用量 / 支出 cap)。短期窓は "叩きすぎたら即 429"、月単位は "使った分だけ請求、または設定上限で停止"。

軸 B: 適用範囲 — User context (OAuth ユーザートークン単位) と App context (アプリの bearer token 単位)。同じ endpoint でも、user context で 75/15min、app context で 450/15min など、別の上限を持つことがあります。

つまり同じ "レート制限" でも、(short window + user)、(short window + app)、(long window + user)、(long window + app) の4種が独立に存在します。本番運用では4つすべてをモニタリングしないと、たまにある特定パターンの 429 が説明できなくなります。

02 — Section

公式 Twitter (X) API の endpoint 別 cap (2026 最新)

docs.x.com の公式 rate-limit ページに掲載されている主要 endpoint の cap を抜粋します。これは pay-per-use 利用時の "short window" 値で、月単位 cap や spending limits とは独立です。

Tweets を読む系:

EndpointUser contextApp context説明
GET /2/tweets/:id900 / 15 min450 / 15 mintweet 個別取得
GET /2/users/:id/tweets900 / 15 min1500 / 15 minuser timeline
GET /2/tweets/search/recent180 / 15 min450 / 15 minrecent search (直近7日)
GET /2/tweets/search/all1 / 1 sec300 / 15 minfull archive search

Users を読む系:

EndpointUser contextApp context説明
GET /2/users/by/username/:un900 / 15 min300 / 15 minusername → user 解決
GET /2/users/:id900 / 15 min300 / 15 minuser 情報取得
GET /2/users/:id/followers15 / 15 min15 / 15 min1000 followers/page
GET /2/users/:id/following15 / 15 min15 / 15 min1000 following/page

書き込み系 はさらに別軸で、POST /2/tweets は 200/15min/user + 100/24h/user の 2 重 cap、DELETE /2/tweets/:id は 50/15min/user — 短時間 burst を許さない設計です。

この表で見えにくいが運用上重要な点: followers の 15/15min は、1ユーザーあたり最大 1000フォロワーを 15分間に 15ページ = 最大 15,000 followers/15min。100万フォロワーのアカウントを全件取得するには 約16時間 かかります。これは公式 cap の物理的下限です。

03 — Section

429 エラーの中身と recovery パターン

429 を返したとき、X API は x-rate-limit-reset ヘッダー に次回利用可能になる Unix timestamp (秒) を含めます。これを見て待つのが正攻法です。素朴な sleep(60) では reset 前に再 hit したり、reset 後すぎたり、いずれにせよ非効率です。

また 429 にも複数バリアントがあります。Type 1: short-window cap (即時、x-rate-limit-reset で15分以内の復旧)。Type 2: monthly cap exceeded (従量課金は 1 請求サイクルあたり投稿読み取り 300 万件が上限。超える場合は Enterprise が必要)。Type 3: spending limits hit (2026 新設、ユーザー設定の月支出上限到達 — x-rate-limit-reset ではなく 403 が返ることもある)。

典型的な recovery パターン (token-bucket + exponential backoff):

  • リクエスト前に in-memory の token-bucket を確認。トークン不足なら次回 refill まで time.sleep()
  • 429 が返ったら、まず x-rate-limit-reset を読み、その時刻まで sleep
  • reset 後の最初のリクエストにも余裕を持たせ、jitter を入れて他のクライアントとの衝突を回避
  • 同一 endpoint に対して 連続 3 回 429 が出たら circuit breaker を発動して 30分間そのワーカーを停止 — wedged な状態を防ぐ
04 — Section

TwitterAPI.io の設計 — 15分 cap がない代わりに何があるか

TwitterAPI.io (第三者 X API) は、endpoint 別の 15分 cap を設定していません。代わりに以下の2層で運用を予測可能にします。

1. Pay-per-call ($0.00015 / read) — 公式 X API ($0.005 / read) の約 1/33 の 1 件あたりコスト。コストは取得件数に比例して線形に積み上がる。

2. 秒単位のレート制限 (アカウント単位) — 初回入金前は 0.2 リクエスト/秒 (5 秒に 1 回)、入金後 (任意のチャージまたはプラン) は 20 リクエスト/秒、Scale プランは 50、Business プランは 500、申請により最大 1,000 リクエスト/秒。超過すると HTTP 429 が返る (Retry-After ヘッダーは付かない)。

つまり、TwitterAPI.io 側で 429 が出るのは 秒間リクエスト数が自分のプランの上限を超えたとき で、1 秒ほど待ってバックオフしながら再試行すれば再開できます。公式 X API のように 15分窓の残量を追跡する必要はありません。

運用上の意味: 大規模 crawler や real-time モニターを書く場合、TwitterAPI.io の方が 15分窓の設計を読まずに済む — 秒間上限を守るシンプルなスロットリングと、コスト・データ可用性だけで意思決定できる。これは特に start-up / 個人開発で大きな差になります。

05 — Section

Python 実装例 — token-bucket + 429 ハンドリング

以下は公式 X API を使う前提の token-bucket リミッター + 429 ハンドリングの最小実装です。/2/users/:id/tweets (timeline 取得) を 900/15min user context で叩く想定。

実装のポイント:

  • TokenBucket は in-memory で、プロセス再起動時にリセット (本番では Redis などに移すべき)
  • x-rate-limit-reset を読んで sleep する分岐を、リクエストの 後 ではなく 429 を受けた瞬間 に挟む
  • backoff は jittered exponential (Full Jitter, https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)
  • 連続 3 回 429 で circuit breaker — 同じ endpoint に対する次のリクエストを 30 分間停止

もし TwitterAPI.io に切り替えるなら、この token-bucket 全体が不要になります — そこが "15分 cap がない" 設計の運用上のメリットです。

06 — Section

endpoint 別 cap 早見表 — 公式 vs TwitterAPI.io

本記事の主要 endpoint について、両 API の short-window cap を1表にまとめます。

Endpoint公式 X API (user / 15min)公式 X API (app / 15min)TwitterAPI.io
Tweet 個別取得90045015分 cap なし (秒単位: 入金後 20 req/秒)
User timeline900150015分 cap なし
Username → user 解決90030015分 cap なし
Recent search18045015分 cap なし
Followers list15 (= 15,000 followers/15min)1515分 cap なし
Tweet 投稿200/15min + 100/24h該当なし投稿エンドポイントあり (人間的なペースを推奨)

実用上の判断軸: Followers list を大量に取得する用途 (audience analytics、KOL discovery 等) では、公式 X API の 15/15min cap が物理的な下限を作る。TwitterAPI.io は 15分 cap がなく、秒間上限とコスト試算だけで運用設計できます。

07 — Section

TwitterAPI.io への移行 — 5 分のクイックスタート

実際に TwitterAPI.io へ移行するときの手順は最小限です。

  1. アカウント作成 — Google サインインのみ。OAuth 4 キーや署名は不要。新規ユーザーには無料のスターター クレジット(約 $0.10、カード不要、31 日で失効)が付与される。
  2. API キー取得 — ダッシュボードから X-API-Key を発行。これを HTTP ヘッダーに X-API-Key: <key> として渡す。
  3. エンドポイント置換 — https://api.twitter.com/2/... → https://api.twitterapi.io/twitter/... への単純な URL 置換。レスポンスフォーマットは X API 互換のため、ほぼ無改修で動きます。
  4. OAuth ロジック削除 — 4 キー (consumer key / consumer secret / access token / access token secret) + リクエスト署名生成のコードが全部不要になる。実コードでは 50-100 行の削減が一般的です。
  5. スロットリング設定 — クライアント側で秒間リクエスト数をプランの上限 (初回入金前 0.2 リクエスト/秒、入金後 20 リクエスト/秒) 以内に抑え、429 が返ったら 1 秒ほど待ち、バックオフしながら再試行します (Retry-After ヘッダーはありません)。

この5ステップで、15分単位の rate-limit 設計について考える必要がなくなります。/2/users/:id/followers のような cap が物理的に効くケースでは、TwitterAPI.io 側で取得スピードが大幅に速くなることもあります (15分 cap がないため)。

python
# pip install requests
import time
import random
import requests

BASE = "https://api.twitter.com/2"
BEARER = "YOUR_X_API_BEARER_TOKEN"


class TokenBucket:
    """Simple in-memory token bucket — 900 tokens / 15 min for /users/:id/tweets."""
    def __init__(self, capacity, refill_seconds):
        self.capacity = capacity
        self.refill_seconds = refill_seconds
        self.tokens = float(capacity)
        self.last = time.time()

    def take(self):
        now = time.time()
        elapsed = now - self.last
        self.tokens = min(self.capacity, self.tokens + elapsed * (self.capacity / self.refill_seconds))
        self.last = now
        if self.tokens >= 1:
            self.tokens -= 1
            return 0  # no wait
        wait = (1 - self.tokens) * (self.refill_seconds / self.capacity)
        time.sleep(wait)
        self.tokens = 0
        self.last = time.time()
        return wait


def get_user_timeline(user_id, bucket, max_attempts=5):
    headers = {"Authorization": f"Bearer {BEARER}"}
    url = f"{BASE}/users/{user_id}/tweets"
    for attempt in range(max_attempts):
        bucket.take()
        r = requests.get(url, headers=headers, timeout=10)
        if r.status_code == 200:
            return r.json()
        if r.status_code == 429:
            # honor server-told reset time
            reset = int(r.headers.get("x-rate-limit-reset", time.time() + 60))
            sleep_for = max(0, reset - time.time()) + random.uniform(0.5, 3.0)  # jitter
            print(f"429: sleeping {sleep_for:.1f}s until reset")
            time.sleep(sleep_for)
            continue
        if r.status_code in (500, 502, 503, 504):
            backoff = (2 ** attempt) + random.uniform(0, 1)
            print(f"{r.status_code}: backoff {backoff:.1f}s")
            time.sleep(backoff)
            continue
        r.raise_for_status()
    raise RuntimeError("max attempts exceeded")


if __name__ == "__main__":
    # 900 tokens / 15 min (user-context cap for /users/:id/tweets)
    bucket = TokenBucket(capacity=900, refill_seconds=900)
    user_id = "REPLACE_WITH_USER_ID"
    data = get_user_timeline(user_id, bucket)
    print("got", len(data.get("data", [])), "tweets")
08 — よくある質問

よくある質問

Twitter (X) API のレート制限はいくつですか?

endpoint 別に異なります。代表的な値: tweets/search/recent は 180/15min (user) / 450/15min (app)、users/:id/tweets は 900/15min (user) / 1500/15min (app)、users/:id/followers は 15/15min (両方)。完全な表は docs.x.com の rate-limit ページに掲載されています。本記事の "endpoint 別 cap 早見表" セクションも参照してください。

429 Too Many Requests が返ったらどうすればいいですか?

(1) x-rate-limit-reset ヘッダーを読み、その Unix timestamp まで sleep する。(2) 復帰後の最初のリクエストに jitter (0.5-3 秒の random sleep) を入れる。(3) 連続 3 回 429 が出たら circuit breaker を発動し、同 endpoint への新規リクエストを 30 分間停止する。本記事の Python 実装例で完結する形のコードを掲載しています。

TwitterAPI.io にはレート制限がありませんか?

公式 X API のような "endpoint 別 15分 cap" はありませんが、秒単位のレート制限があります: 初回入金前 0.2 リクエスト/秒 (5 秒に 1 回)、入金後 20 リクエスト/秒、Scale プラン 50、Business プラン 500、申請で最大 1,000 リクエスト/秒。超過すると HTTP 429 が返ります。Retry-After ヘッダーは付かないため、1 秒ほど待ってバックオフしながら再試行します。課金は pay-per-call ($0.00015/ツイート) で線形に積み上がります。

User context と App context の cap の違いは何ですか?

User context は OAuth ユーザートークン単位の cap で、特定のユーザーが行う操作 (自分の DM 取得、自分の followers 取得など) に適用されます。App context は アプリ全体の bearer token 単位の cap で、public data の取得 (任意のユーザーの public tweets など) に使われます。同じ endpoint でも user / app で別の上限値が設定されているのが標準です。

月の合計使用量に上限はありますか?

あります。2026 年現在の pay-per-use モデル (サブスクリプションなし) では、1 請求サイクルあたり投稿読み取り 300 万件が上限で、それを超える場合は申込フォーム経由の Enterprise (価格非公開) が必要です (docs.x.com 確認)。上限の範囲内では、ユーザー側の spending limits で billing cycle 単位の最大支出額を設定できます。

Followers list の取得が遅すぎる場合の対処法は?

公式 X API の users/:id/followers は 15/15min × 1000/page = 60,000/h が物理的な上限です。100万フォロワーのアカウントを全件取得するには約16時間。短縮する選択肢は (1) Enterprise 契約を検討する (申込フォーム経由、価格非公開)、(2) TwitterAPI.io の followers/ids への移行 (15分 cap がない、5000 IDs/page、コストも大幅に低い)、または (3) 取得対象を最新 N% のフォロワーに絞る、のいずれかです。

Tweet 投稿のレート制限は何ですか?

公式 X API の POST /2/tweets は user context で 200/15min + 100/24h の 2 重 cap。DELETE /2/tweets/:id は 50/15min。これらは burst を許さない設計で、bot/automation の濫用防止が目的です。書き込み系は本記事の主題ではありません。TwitterAPI.io も投稿・いいね・リツイート・フォローなどの書き込みエンドポイントを提供していますが、凍結リスクを避けるため人間的なペースで使ってください。

09 — 関連記事

続けて読む

参考にした一次資料
関連シリーズ
実装に進む

読むのをやめて、作り始めよう。

無料の試用クレジットで本物のデータを使った E2E テストが完結します。Google サインインのみ、カード不要、申請待ちなし。

API キーを取得