post-cover

弊社では Amazon楽天でスポーツバッグを販売しており、その分析と改善提案を OpenClaw にやらせる取り組みを進めています。

その中で、X には EC に関する有益な情報を継続的に発信している人がいるので、その知見も組み合わせて EC の成長に役立てたいと考え、X API を使って投稿を取得してみました。

今回は、あるアカウントの 2025 年 1 年間の投稿件数 と、投稿の種類である 投稿、返信、リポスト、引用リポスト を調べました。 すると、それだけで $15.88、約2,500円 の費用が発生しました。

しかも、やったことは大がかりな分析ではなく、まず件数や内訳を把握したいという確認に近いものでした。

X API は「何回実行したか」よりも、実際に何件の投稿を読んだかで費用が膨らみやすいため、長期間をまとめて取りにいくと、試験実行でもすぐに金額が大きくなります。

X APIの高額請求対策

やるべきこともシンプルです。

  • 返信とリポストを最初から API 側で除外する
  • まずは 7 日や 30 日など短い期間だけ取得する

この記事では、まずこの結論を押さえたうえで、実際にどんな流れで試し、どこでコストが膨らみ、サンプルコードではどう対策したかを順番に説明します。

なお、この記事で紹介するサンプルコードは以下のリポジトリにまとめています。

実際にやったこと

実際の作業は、だいたい次の順番で進めました。

  1. X Developer Console のアカウントを作る
  2. API キー類を取得する
  3. x-api-samples/.env に設定する
  4. 疎通確認スクリプトを実行する
  5. 特定アカウントの投稿を取得する
  6. どこで費用が膨らんだのかを整理する
  7. 費用を抑える運用ルールを入れる

前提

今回反映したサンプルは、x-api-samples リポジトリに最小構成で置いてあります。

主なファイル:

  • scripts/check-x-api.ts
  • scripts/fetch-x-account-posts.ts
  • scripts/lib/x-api.ts
  • .env.example

このサンプルは Node.js 20 以上を前提にしており、tsx で TypeScript を直接実行します。

なお、公開しているサンプルは、今回実際に費用が膨らんだ取り方をそのまま再現するものではありません。 既定では 1 週間分だけ を対象にし、さらに オリジナル投稿と引用投稿に絞る 形にしてあります。

そのため、この記事で触れている「2025 年の 1 年分を広く読んでしまって高額になったケース」と比べると、サンプルの方はとんでもない金額になりにくい作りです。

1. X Developer Console のアカウントを作る

まず X Developer Console で開発者アカウントを作成し、Project と App を作ります。

その後、App から認証情報を取得します。

今回のサンプルでは、以下の値を使います。

  • X_API_KEY
  • X_API_KEY_SECRET
  • X_BEARER_TOKEN
  • X_ACCESS_TOKEN
  • X_ACCESS_TOKEN_SECRET
  • X_TARGET_USERNAME

それぞれの役割は次の通りです。

  • X_BEARER_TOKEN 公開データの読み取りに使います。特定アカウントの情報取得やタイムライン取得は Bearer Token で行っています。
  • X_API_KEY OAuth 1.0a の consumer key です。
  • X_API_KEY_SECRET OAuth 1.0a の consumer secret です。
  • X_ACCESS_TOKEN OAuth 1.0a の user access token です。
  • X_ACCESS_TOKEN_SECRET X_ACCESS_TOKEN に対応する secret です。
  • X_TARGET_USERNAME 取得対象アカウントのユーザー名です。

このサンプルでは、疎通確認 scripts/check-x-api.ts で OAuth 1.0a User Context を使って GET /2/users/me を叩くため、投稿取得だけ試す場合でも .env には 5 つの認証値を入れておく前提にしておく方が分かりやすいです。

2. x-api-samples/.env に設定する

リポジトリをクローンしたら、まず依存関係を入れます。

npm install

次に .env.example をコピーして .env を作ります。

cp .env.example .env

Windows PowerShell の場合:

Copy-Item .env.example .env

.env.example をベースに、少なくとも次の値を設定します。

X_API_KEY=...X_API_KEY_SECRET=...X_BEARER_TOKEN=...X_ACCESS_TOKEN=...X_ACCESS_TOKEN_SECRET=...X_TARGET_USERNAME=...

必要に応じて、取得期間も指定できます。

X_TARGET_START_TIME=2026-01-01T00:00:00.000ZX_TARGET_END_TIME=2026-01-07T23:59:59.000Z

サンプルコードでは、X_TARGET_START_TIMEX_TARGET_END_TIME を省略した場合、既定で 2026 年 1 月 1 日から 2026 年 1 月 7 日まで を対象にします。

これは、いきなり長期間を読んでコストが膨らまないようにするためです。

3. まず疎通確認をする

最初にやるのは疎通確認です。

npm run check:x-api

このスクリプトでは、次の 2 つを確認します。

  1. OAuth 1.0a User Context で GET /2/users/me
  2. Bearer Token で GET /2/users/by/username/:username

つまり、scripts/check-x-api.ts では、

  • OAuth 1.0a のキー類が正しいか
  • Bearer Token が正しいか
  • 自分のアカウント情報と公開ユーザー情報の取得が通るか

をまとめて確認できます。

認証情報が誤っていると、この段階で止まるので、余計な投稿取得を走らせずに済みます。

4. 特定アカウントの投稿を取得する

疎通確認が通ったら、実際に対象アカウントの投稿を取得します。

npm run fetch:x-posts

このスクリプト scripts/fetch-x-account-posts.ts では、次のことを行います。

  • X_TARGET_USERNAME からユーザー ID を取得する
  • GET /2/users/:id/tweets でタイムラインを取る
  • exclude=replies,retweets を付けて、返信とリポストを API 側で除外する
  • オリジナル投稿と引用投稿だけを保存する
  • 初回取得後は、保存済み latest の先頭投稿 ID を since_id として使い、増分取得する
  • 投稿に紐づくメディア情報を保存する
  • 画像 URL が取れたものはローカルにダウンロードする

保存先は以下です。

  • 累積データ: analysis/x/data/raw/account-posts-latest.json
  • 増分データ: analysis/x/data/raw/account-posts-incremental-latest.json
  • スナップショット: analysis/x/data/raw/account-posts-<timestamp>.json
  • 画像ファイル: analysis/x/data/media/

JSON には、投稿本文だけでなく classificationpublic_metricsattachmentsmedia なども含まれます。

5. 取得対象はオリジナルと引用だけにする

今回の要件では、欲しいのは以下だけです。

  • オリジナル投稿
  • 引用投稿

不要なもの:

  • 返信
  • 引用なしのリポスト

ここで重要なのは、取ってから捨てるのではなく、API 側で先に除外することです。

scripts/fetch-x-account-posts.ts では、fetchUserTimelinePage() に対して次の指定を入れています。

exclude=replies,retweets

この指定で、返信とリポストを API の返却段階で外せます。 サンプル内では、そのうえで referenced_tweets を見て original / quote / reply / repost に分類しています。

料金面でもここは重要です。 X API の 投稿: 読み取り は、取得した投稿 1 件ごとに課金されます。 つまり、返信やリポストまで読んでしまうと、その分そのまま費用が増えます

6. 期間はできるだけ短くする

今回の反省点のひとつがこれです。

対象アカウントは 2020 年 5 月ごろから X を使っていて、2026 年 4 月時点で総投稿数は 9,000 件前後でした。 その数字を見て、「6 年近くで 9,000 件程度なら、2025 年の 1 年分を試しに取るくらいなら大した件数にはならないだろう」と考えてしまいました。

そこで、2025 年の 1 年分をお試しで取得してみたところ、実際には 3,172 Post reads / $15.88 になりました。 テストのつもりで動かしただけだったので、想像以上に大きい金額になってしまいました。

つまり、件数確認だけのつもりでも、長期間をフルに読むと、その分だけ費用が乗るということです。

最初からやるべきだったことは次の 3 つです。

  • まず 7 日や 30 日など短い期間で試す
  • 返信とリポストを API で除外する
  • 本当に必要な期間だけを広げる

今回のサンプルで既定期間を 1 週間にしているのも、この反省からです。

7. 今回のミス

今回の実運用では、以下のような流れになりました。

  1. 疎通確認をした
  2. 期間内の投稿件数を確認した
  3. 実際に投稿を保存した

このうち、問題だったのは 件数確認のために広い期間のタイムラインを読んだことです。

結果として、Usage API 上の実消費は以下でした。

  • project_usage = 3172

請求側では以下でした。

  • 総費用: $15.88
  • 総投稿数: 3.17K

X Developer Platform の pricing では、投稿: 読み取り$0.005 / リソース とされています。 つまり、投稿 1,000 件で 5 ドルです。

今回の 3,172 件をこの単価で計算すると、次の通りです。

3,172 × $0.005 = $15.86

実際の請求が $15.88 だったので、ほぼこの単価どおりに課金されたと考えてよさそうです。

参考:

8. 重複課金を避ける仕組みはある

救いがある点として、X API の Usage ドキュメントでは、同じリソースを 24 時間の UTC 窓内で繰り返し取得しても、原則として重複課金を避ける仕組みがあると説明されています。

要するに、同一の投稿や同一のユーザーなどを同日内に何度も取り直しても、通常はその分を何重にも課金しない前提です。

ただし、これを前提に雑に再取得するべきではありません。 日付をまたいで再取得すれば費用が発生する可能性がありますし、将来的に仕様や課金条件が変わる可能性もあります。

つまり、「今は重複課金を避ける仕組みがあるらしいから何度取り直しても大丈夫」と考えるのではなく、そもそも不要な再取得をしない設計にしておく方が安全です。

運用上は、次の方針にするべきです。

  • 同じ条件の再取得は避ける
  • まずローカル保存済みファイルを確認する
  • account-posts-latest.json を再利用する
  • 増分取得を前提にする
  • 課金仕様が変わっても困らない作りにしておく

参考:

9. 低コストにする実務ルール

今回の反省と、今回のサンプル実装から言える実務ルールは以下です。

1. 取得対象を先に絞る

  • オリジナル投稿と引用投稿だけを対象にする
  • 返信とリポストは API 側で除外する

2. 期間を短くする

  • まず 7 日
  • 次に 30 日
  • 必要なら 90 日
  • 問題なければ広げる

3. いきなりフル取得しない

  • 件数確認のために長期間のフルページングをしない
  • 小さい期間で先にサンプル取得する

4. 増分取得を使う

サンプルでは、保存済み analysis/x/data/raw/account-posts-latest.json の先頭投稿 ID を読んで、次回以降は since_id を付けた増分取得に切り替えます。

これにより、毎回過去分を読み直さずに済みます。

5. 保存済みデータを使う

  • latest を見てから API を叩く
  • 同じ目的で何度も取得しない
  • 差分だけが必要なら account-posts-incremental-latest.json を見る

10. このリポジトリでのおすすめ手順

費用を抑えつつ始めるなら、以下の順序が安全です。

  1. git clone https://github.com/isec-promotion/x-api-samples.git
  2. npm install
  3. .env.example をコピーして .env を作成する
  4. X_TARGET_USERNAME と認証情報を設定する
  5. まず 7 日程度の期間を X_TARGET_START_TIME / X_TARGET_END_TIME で指定する
  6. npm run check:x-api を実行する
  7. npm run fetch:x-posts を実行する
  8. 2 回目以降は保存済み latest を前提に増分取得する

まとめ

X API のように従量課金のサービスを扱う場合、 重要なのは「どうやって取得するか」だけでなく、 どうやって無駄に取得しないか です。

今回のケースでは、単なる件数確認のつもりで 1 年分を取得した結果、 約2,500円の請求 が発生しました。

この程度で済んだからよかったものの、もし AI に処理を丸投げしていた場合、 気づかないまま大量のデータ取得が走り続け、 後から高額な請求になる可能性も十分にあります。

OpenClaw のような AI エージェントは非常に強力ですが、 「動かせる」ことと「安全に運用できる」ことは別物 です。

API を使った自動化を行う場合は、必ず以下を徹底してください。

  • 最初は小さい範囲で実行する(期間・件数を制限)
  • 何件取得されるか、どれくらい課金されるかを事前に把握する
  • 一度人間が結果を確認してから本番運用に移す
  • 無駄な取得が起きない設計(除外・増分取得)にする

AIは便利ですが、コストに関しては気を遣ってくれない可能性があります。 だからこそ最後の責任は人間が持つ必要があります。

「まず人間が確認してから自動化する」

これを前提に設計することが、AI時代の開発では必須です。

SNSでシェアしよう

この記事が役に立ったら、ぜひシェアしてください