Contents
1. 全体像と主要エンドポイントの上限
1‑1. レートリミットの構造
X API は 時間単位(1 hour) と 日次(24 hours) の二層構造でクォータを管理します。
| 階層 | 主な目的 |
|---|---|
| 時間単位リミット | 瞬間的なトラフィックスパイクやボット行為の抑止 |
| 日次クォータ | 月額プランごとの総利用上限を保証し、長期的な安定運用を支援 |
時間単位リミットが逼迫すると、同一日の残りクォータも自動で減少する仕組みです(公式ガイドライン参照[^1])。
1‑2. エンドポイント別上限(Free / Pro)
| エンドポイント | 1 hour 上限 (Free) | 1 day 上限 (Free) | 1 hour 上限 (Pro) | 1 day 上限 (Pro) |
|---|---|---|---|---|
ツイート取得 (/2/tweets) |
300 リクエスト | 5,000 リクエスト | 3,600 リクエスト | 86,400 リクエスト |
ユーザー検索 (/2/users/by) |
180 リクエスト | 4,320 リクエスト | 2,160 リクエスト | 51,840 リクエスト |
ツイート作成 (POST /2/tweets) |
50 POST | 1,200 POST | 600 POST | 14,400 POST |
DM/リプライ (/2/direct_messages/events) |
30 POST | 720 POST | 300 POST | 7,200 POST |
※ 表は公式「Rate Limits」ページに掲載されている代表的数値です。実際のクォータは契約内容や過去の利用状況に応じて微調整されることがあります(詳細は API コンソールの Usage タブ)。
1‑3. リミット設計上のポイント
- 優先的にモニタリングすべき指標
remaining(残りリクエスト数) – 時間単位と日次それぞれ。-
reset(リセット時刻) – 秒単位で返却されるため、正確な待機時間算出に必須。 -
プラン選定のヒント
- Free:開発・テスト向け、1 hour ≤ 300 が目安。
- Pro:本番サービスやデータ分析向け、1 hour ≥ 3,600 が安全マージン。
2. プラン別クォータと料金
2‑1. プラン構成(2026‑02‑24 更新)
| プラン | 月額 (USD) | 時間単位上限(主要エンドポイント) | 日次総クォータ | 主な利用可能機能 |
|---|---|---|---|---|
| Free | $0 | ツイート取得 300、投稿 50 | 5,000 リクエスト | 基本的なツイート取得・検索 |
| Basic | $99 | ツイート取得 900、投稿 150 | 15,000 リクエスト | 上記+リプライ作成・限定 DM |
| Pro | $499 | ツイート取得 3,600、投稿 600 | 86,400 リクエスト | 全エンドポイント+高度分析 |
| Enterprise | カスタム | 契約ベースで「実質無制限」 | 契約ベースで「実質無制限」 | SLA・専用サポート・拡張機能 |
価格は米ドル表記、税別です。日本円換算やボリュームディスカウントは公式見積もりをご参照ください[^2]。
2‑2. コスト最適化のチェックポイント
| 項目 | 評価基準 |
|---|---|
| 必要エンドポイント数 | 使用予定 API の総数と頻度をシミュレーション |
| ピーク時リクエスト量 | 1 hour リミットが 80 % 以下になるよう余裕を持つ |
| 長期的なデータ取得 | 日次クォータが月間利用予測の 90 % 未満であること |
3. レートリミット超過時の対策
3‑1. 主なエラーコードと意味
| コード | 意味 | 推奨アクション |
|---|---|---|
| 429 | Too Many Requests(時間単位リミット) | Retry-After ヘッダーの秒数待機 → 指数バックオフで再試行 |
| 403 | Forbidden(日次クォータまたは権限不足) | クォータリセットまで待機(通常 24 h) |
| 500 系列 | サーバ内部エラー | 短時間のバックオフ後に再試行 |
3‑2. 安全な指数バックオフ実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import time, random, requests def request_with_backoff(url, headers, max_attempts=5): base = 1 # 秒 for attempt in range(1, max_attempts + 1): resp = requests.get(url, headers=headers) if resp.status_code == 429: wait = int(resp.headers.get("Retry-After", base * (2 ** attempt))) jitter = random.uniform(0, 0.5) # 0〜0.5 秒のジッタ time.sleep(wait + jitter) else: resp.raise_for_status() return resp.json() raise RuntimeError("最大リトライ回数に達しました") |
ポイント
- Retry-After が存在すればそれを優先。
- ジッタ(乱数)を加えることで同時再試行集中を緩和します。
3‑3. キュー活用のベストプラクティス
| ツール | 用途 |
|---|---|
| Amazon SQS / RabbitMQ | 失敗リクエストを遅延キューに入れ、バックオフ時間が経過したら再投入 |
| Dead‑Letter Queue (DLQ) | 最大リトライ回数超過時に保管し、手動レビュー用に活用 |
4. リクエスト最適化ベストプラクティス
4‑1. バッチング(複数 ID の同時取得)
|
1 2 |
GET https://api.x.com/2/tweets?ids=123,124,125,126&tweet.fields=id,text,created_at |
- 効果:4 件のツイート取得が 1 リクエストに集約 → リミット消費を 75 % 削減。
4‑2. 必要フィールドだけを取得
|
1 2 |
GET https://api.x.com/2/users/by?usernames=alice,bob&user.fields=id,username,public_metrics |
fieldsパラメータで不要情報を除外し、レスポンスサイズと帯域コストを最小化。
4‑3. キャッシュ戦略
| 層 | 実装例 | TTL 推奨 |
|---|---|---|
| サーバ側 | Redis tweet:{id} キーで保存 |
300 秒(5 分) |
| クライアント側 | Service Worker の Cache API | 60 秒 |
キャッシュヒット率が高いほど、レートリミットへの圧迫は指数的に低減します。
5. モニタリングとアラート設計
5‑1. X API Dashboard と CloudWatch の連携フロー
- Dashboard で利用状況取得
-
GET https://api.x.com/2/application/rate_limit_status(Bearer トークン必須)[^3] -
CloudWatch カスタムメトリクスへプッシュ(例:Python Lambda)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import boto3, requests, os cw = boto3.client('cloudwatch') resp = requests.get( "https://api.x.com/2/application/rate_limit_status", headers={"Authorization": f"Bearer {os.getenv('X_BEARER_TOKEN')}"} ) data = resp.json() for ep, stats in data["resources"].items(): cw.put_metric_data( Namespace='XAPI', MetricData=[{ 'MetricName': 'RateLimitRemaining', 'Dimensions': [{'Name': 'Endpoint', 'Value': ep}], 'Value': stats['remaining'], 'Unit': 'Count' }] ) |
- アラート設定
-
CloudWatch アラームで
RateLimitRemaining ≤ 20(プランに応じて閾値調整) → SNS トピック経由でメール/Slack に通知。 -
自動復旧例
- アラート受信時に Lambda がバックオフパラメータを緩め、短期的なリクエスト削減策(キャッシュ優先度上げ)を適用。
5‑2. 可視化のポイント
| ダッシュボード項目 | 推奨表示形式 |
|---|---|
| 残りリクエスト数 | 棒グラフ+リアルタイム数値 |
| リセットまでの秒数 | カウントダウンタイマー |
| エラー率(429/403) | パーセンテージ円グラフ |
6. 実装サンプルとスケーラビリティ指針
6‑1. Python でのレートリミットハンドリング
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import time, random, requests from backoff import on_exception, expo BASE_URL = "https://api.x.com/2" TOKEN = "YOUR_BEARER_TOKEN" @on_exception(expo, (requests.exceptions.HTTPError,), max_tries=5) def fetch_tweets(ids): params = {"ids": ",".join(map(str, ids)), "tweet.fields": "id,text,created_at"} headers = {"Authorization": f"Bearer {TOKEN}"} resp = requests.get(f"{BASE_URL}/tweets", params=params, headers=headers) if resp.status_code == 429: wait = int(resp.headers.get("Retry-After", "60")) time.sleep(wait + random.uniform(0, 1)) raise requests.exceptions.HTTPError("Rate limit exceeded") resp.raise_for_status() return resp.json() # バッチング利用例 print(fetch_tweets([123,124,125,126])) |
backoff ライブラリが指数バックオフとジッタを自動化します。
6‑2. Node.js(axios + retry‑axios)実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
const axios = require('axios'); const rax = require('retry-axios'); const client = axios.create({ baseURL: 'https://api.x.com/2', headers: { Authorization: `Bearer ${process.env.X_BEARER}` } }); client.defaults.raxConfig = { instance: client, retry: 5, backoffType: 'exponential', onRetryAttempt: err => { const cfg = rax.getConfig(err); console.log(`リトライ #${cfg.currentRetryAttempt}`); } }; rax.attach(client); async function getUsers(usernames) { try { const res = await client.get('/users/by', { params: { usernames: usernames.join(','), 'user.fields': 'id,username' } }); return res.data; } catch (e) { if (e.response?.status === 429) { const waitSec = parseInt(e.response.headers['retry-after'] || '60', 10); await new Promise(r => setTimeout(r, (waitSec + Math.random()) * 1000)); throw e; // retry‑axios が再実行 } throw e; } } // バッチング例 getUsers(['alice','bob']).then(console.log).catch(console.error); |
6‑3. スケーラビリティ設計指針
| 項目 | 推奨アーキテクチャ |
|---|---|
| 水平分散 | 複数ワーカー(K8s Pod)で API 呼び出しを均等割り振り、Pod Autoscaler で負荷に応じ自動増減 |
| マイクロサービス化 | 「ツイート取得」「ユーザー検索」「投稿」ごとに独立サービスを作り、各サービスが個別のレートリミット管理ロジックを保持 |
| キャッシュ層 | Redis Cluster(5‑10 分 TTL)で頻出データを永続化し、同一リクエストの再取得を防止 |
| バージョン耐性 | API バージョン (/2/) をコードベースに定数化し、バージョンアップ時は CI で自動テストを走らせる |
| 監視・ロギング統合 | CloudWatch Logs と X API Dashboard のメトリクスを一元化し、異常検知時に自動ロールバックパイプラインへ連携 |
まとめ
- レートリミットは時間単位と日次の二層構造。どちらもモニタリングし、特に時間単位の残り数が 80 % 以下になる前に対策を取ることが重要です。
- プラン選定は「必要エンドポイント × 想定呼び出し頻度」でシミュレーションし、Free→Basic→Pro→Enterprise の順に段階的に上げていくとコスト最適化できます。
- 429/403 エラーが返ったら必ず
Retry-After待機+指数バックオフを実装し、キューや DLQ で失敗リクエストを管理しましょう。 - バッチング・フィールド限定取得・キャッシュの組み合わせでリクエスト数は最大 70 % 削減可能です。
- Dashboard と CloudWatch の連携により、利用率が閾値に近づいた瞬間に自動通知・自動復旧を実装できます。
- スケーラビリティは水平分散+マイクロサービス化+キャッシュ層で確保し、コードベースは API バージョン変化に耐える設計とします。
これらの指針を踏まえて実装すれば、レートリミットによる障害リスクを最小限に抑えつつ、X API を活用したプロダクトの安定運用が実現できます。
[^1]: X Developer Platform – Rate Limits(2026‑02‑24)https://developer.x.com/en/docs/twitter-api/rate-limits
[^2]: X Developer Platform – Pricing(2026‑02‑24)https://developer.x.com/en/pricing
[^3]: X Developer Platform – Application Rate Limit Status API(2026‑02‑24)https://developer.x.com/en/docs/twitter-api/v2/reference/get-application-rate_limit_status