AIにXの投稿を取らせる正規ルート|規約と従量課金に制限をつけて繋ぐ

いいねしたあの投稿、結局読み返してないですよね

ども!龍ちゃんです。最近、技術の話って Web じゃなくて X に集まってきてませんか。僕はけっこうそう感じていて、しかも「あとで読もう」と思ったやつほど流れていくんですよね。

最近読んだ中で印象に残っているのが、@HayattiQ さんのこの投稿です。AI に「X の今」を調べさせると途端に精度が落ちるのは、AI の能力ではなく情報源の性質の問題だ、という指摘で。この投稿自体が「X の中にしかない知見」の実例になっているのが面白いんですよね。

正直に言うと、僕もいいねだけして溜め込んでいるクチです。あとで読み返すつもりではいるんですが、実際にコピペして手元に持ってくるのは気が向いたときだけ。数えてみたら月1本くらいでした。

そこで、X API を正規に契約して、Claude Code から叩ける CLI と skill を作りました。いまは記事を読んでいて「これ取っておいて」と言えば、本文が手元に落ちてくるようになっています。

今日話すのはこの4つです。

  • 何をやったらダメなのか
  • 許された道はいくらか
  • 実際にどう作ったか
  • で、何が変わったか

順番に見ていきますね。

そもそも、何をやったらダメなんだろう

「X の投稿を機械で集める」って調べると、無料の抜け道と有料の正規ルートが混ざって出てくるんですよね。ここを先に整理しておかないと、値段の話にも進めないので、きちんと公式に行って「何がダメなのか」を確定させます。ダメには2つの層があります。

機械には、はっきり「来るな」と書いてある

機械で触る前に、まず見にいくのが x.com/robots.txt です。これはクローラー向けに「何を取っていいか」を宣言するためのファイルで、ブラウザで開けば誰でも読めます。

中身はこうでした(2026-09-10 取得)。

User-agent: *
Disallow: /

User-agent: * はすべてのクローラが対象で、Disallow: / はサイト全体を禁止する、という意味なんですよね。そのうえで、名指しで許可されているクローラが3つだけあります。Googlebot、Bingbot、facebookexternalhit です。それ以外は、この一行だけで門前払いということになります。

しかも Google-Extended など AI 向けのクローラ7つは、個別に名指しで拒否されています。検索エンジンには来ていいと言いながら、AI には来るなと言っている形なんですよね。

robots.txt はあくまで宣言で、鍵ではありません。でも、X が誰に来てほしくて誰に来てほしくないかは、これで十分伝わってきました。この宣言をどう受け止めるかは、次の規約の話に譲りますね。

規約が、公式 API 以外の自動収集を禁じている

出典は X Developer Guidelines(2026-09-10 取得)です。禁止行為の表に、こう並んでいます。

Non-API Automation: Browser scripting, scraping, any automation outside official API

公式 API を通らない自動アクセスは全部そこに入っていて、ブラウザ操作もスクレイピングも名指しです。帰結も同じページにはっきり書いてあります。Non-API automation (scraping, browser automation) results in permanent suspension. つまり、アカウントの永久停止です。

正直、非公式のツールやライブラリは実際に動くんですよね。動いてしまいます。でも、動くこととやっていいことは別の話で。

これ、AI 固有の規制ではないんですよね。「AI に取らせるのがダメ」ではなく「公式 API を通らない自動収集がダメ」という話で、人が書いたスクリプトでも同じ扱いになります。どのツールが白でどれが黒かの品評はしませんし、禁止されているのは X 上のコンテンツ(投稿やプロフィール)を機械で集めることであって、開発者向けドキュメントを読みにいくことは別の話です。

もう一つ、取ったあとの話も同じ規約の隣にあります。Developer Policy は、X のコンテンツをオフラインに保存するなら X 上の状態に合わせて更新し続けること、削除や変更があれば24時間以内に追従することを求めています。本文も画像も同じ扱いです。つまり正規ルートで取ること自体は問題なくても、手元に溜めた瞬間に「X で消えたら消す」義務が付いてきます。今回は本文は手元に置いているので、この義務を引き受けている側です。月に数件なので手で追えますが、溜め込む設計にするなら削除に追従する仕組みまで要る、ということは先に知っておいたほうがいいです。

なお、ここで扱うのは「取る」話だけです。出す(投稿する)側の自動化はAIチャットで話すだけ!X予約投稿を完全自動化するシステム構築術に書きました。

じゃあ、許された道はいくらなんだろう

「X の投稿は取れない」わけじゃないんですよね。正確には「タダでは取れない」です。公式にお金を払ってAPIを使おうねって話です。

入口は2つある。どちらも同じ財布に乗る

許された道は2つあります。ひとつは公式 API を自分で叩くこと、もうひとつは公式の MCP サーバ(xmcp)を繋ぐことです。MCP を繋ぐと、AI が自分でその場から API を叩けるようになります。ただ、xmcp を繋いでも請求は結局こちらの API プランに乗ります。少なくとも僕が調べた範囲では、MCP 経由なら無料になるという枠は見つかりませんでした。繋ぎ方は公式が X MCP Server にまとめてくれているので、ここでは同じ財布に乗るということだけ触れておきます。

無料枠はもう消えていて、読み取りは1リソース $0.005

X API の料金ページを開くと、載っているのは従量課金の説明だけで、無料で使える枠の案内はどこにも見当たりません。以前は無料枠があったので、「まずは無料で試してみましょう」と書いてある記事はもう前提が違うんですよね。読み取りは $0.005 / リソースと書いてあります。

で、実際どうやって取るの

先に済ませておくことが2つあります

やることは2つで、認証情報を1つ発行することと、クレジットを買っておくことです。

ひとつ目。開発者アカウントを作ってアプリを作ると、認証情報がいくつか発行されます。API Key、API Secret、Access Token……と並ぶので身構えるんですが、投稿を読むだけなら Bearer Token 1つで足ります。残りはユーザーの代理で動くとき(投稿する側)に使うものです。手順は公式の Getting Access が3ステップで書いてくれています。

ふたつ目。クレジットを先に買っておきます。 X API には無料枠が無いので、アカウントとトークンを揃えても、クレジットが入っていなければ何も取れません。Getting Access の次のページは、もう「最初のリクエストを送ろう」です。 ちなみに僕が買ったときは、クレジットの最低チャージ金額が「$5」でした。日本円だと760円ぐらいですね(2026-09-10 時点)。 「円安やべ〜」とは思いました。でも、必要なコストだと割り切ってAPIのクレジットを買っておきましょう。1件 $0.005 なので、1件だけのつもりで払っても1000件ぶんが残る計算になります。

公式 MCP があるのに、自前で CLI を作りました

公式 MCP を繋ぐと投稿取得・全文検索・ユーザー・タイムライン・ブックマーク・Article など道具が束で載り、どれを使うかはプロンプトが決める。自前の CLI は投稿を1件取る機能しかなく、まとめ取りはそもそもできない

理由は2つあります。

ひとつは、やりたいことがすごく狭かったこと。記事を読んでいて X のリンクを見つけたときに、本文を全文コピペするんじゃなくて、URL を渡したら手元に落ちてくる。欲しかったのはそれだけなんですよね。X に対して何でもできる口を開けておく理由がありませんでした。

もうひとつは、従量課金を AI に自由に叩かせたくなかったこと。怖かったのは、リクエスト単位で請求が立つことです。叩いた瞬間に金が減ります。それに、もし自動でクレジットが補給される設定になっていたら、残高が切れても止まらないんじゃないか、とも思いました。ここは仕様を確認していません。確認していないので、最悪のほうに倒して設計することにしました。止まらない前提で組んでおけば、実際に止まる仕様だったとしても損はしないので。

もう少し言うと、MCP は道具が束で載っている形なんですよね。繋いだ瞬間に使える口がいくつも開いて、そのどれをどう使うかは、その場のプロンプト次第になります。使ってほしくない使い方を止めたければ、お願いするしかない。 自前の CLI にすると、そこが変わります。縛るのが言葉じゃなくて機能の形になるので、たとえばまとめ取りは「やらないでね」ではなく「そもそもできない」になるんです。

公式の MCP(xmcp)を繋いでも、叩く前に確認を挟むこと自体はできます。Claude Code は MCP 経由のツール呼び出しにもちゃんと確認ダイアログを出してくれるので、そこは正直に認めておきたいです。ただ、あのダイアログが聞いてくれるのは「叩いていいか」だけなんですよね。

実行そのものは CLI 側に制約として持たせて、すでに取得済みの投稿かどうかの確認は skill に手順として持たせています。人間がやることとしては、X のリンクを共有するだけですね。

  • Step 0: 叩く前に、すでに取得済みかを確認する(同じ投稿を二度取らない)
  • Step 1: 2件以上は件数と概算費用を先に申告して合意を取る

まとめて取る機能をあえて作っていないのも同じ理由です。金が減る操作は狭いところから始めるほうが安全で、狭くて困ったら後から足せても、広くしてから事故ると戻せないからです。

叩いてみると、レスポンスで2回つまずきます

僕は自作の CLI から叩いていますが、やっていることはこの curl 1本と変わらないので、そのまま打てる形で書きます。

curl -H "Authorization: Bearer $BEARER_TOKEN" \
  "https://api.x.com/2/tweets/<post_id>?tweet.fields=article,created_at,public_metrics&expansions=author_id,article.cover_media,article.media_entities&media.fields=url"

先に1つだけ。返ってきた生の JSON は必ずファイルに残してください。 叩いた時点でもう金は減っているので、捨てると同じ金を払って取り直すことになります。僕はレスポンスとヘッダーの原本を _raw/ に、消費クレジットの台帳を1行1件で残すようにしました。

ここからが本題です。いちばん時間を溶かしたのがレスポンスの読み方でした。素直に叩くと、text には23字しか入っていなくて焦ります。本文は article.plain_text のほうに全文入っていて、実測で1,647字ありました。冒頭の抜粋じゃなくて末尾まで、です。

Article 付きの投稿の実例と、tweet.fields を指定しないと本文は data.text の23字しか返らず、tweet.fields=article を指定すると article.plain_text に1,647字の全文が返ること。料金はどちらも同じ $0.005

しかもこの article は、リクエストで tweet.fields=article を明示しないとそもそも返ってきません。指定せずに GET /2/tweets/<id> を叩くと、返ってくるのは23字のほうだけです。公式ドキュメントには article のサブフィールドの定義が無いので(2026-09-09時点)、何が返ってくるかはドキュメント側からは埋められず、実測でしか分かりませんでした。

もうひとつ、画像でも踏みました。最初に取ったとき、Article の本文中の画像は ID のまま残って、実体で返ってきたのはカバー画像1枚だけだったんですよね。原因は僕の指定漏れで、expansionsarticle.media_entities を足すだけで、本文中の画像も同じ1回の includes.media に URL 付きで返ってきます。実測だと本文の画像2枚とカバー1枚の計3枚が全部入りました。通常の投稿に添付された画像も同じで、こちらは attachments.media_keys です。どちらも media.fields=url を付けないと media_keytype しか返らないので、そこだけ注意です。

返ってくる URL は pbs.twimg.com のもので、そこから先は認証なしの普通の GET で落ちます。?format=jpg&name=orig を付ければ原寸です。includes 側なので追加の課金は無く、コンソールの累計も投稿ぶんしか動いていませんでした。

ただ、落とした画像ファイルを手元に置くのはやめました。最初に書いた削除追従の義務は画像にも同じに掛かるからです。持たなければ負わないので、URL だけを保存して、中身が要るときに CDN から読んで、読んだら消すようにしています。将来的には、投稿も自分の環境に生かせる内容として取り込んだら消す運用にする予定です。

結局いくら払っているのか、確かめてみる

レスポンス自体は消費クレジットを返してくれません。ヘッダーまで全部見ても、課金に関係するのは rate-limit 系だけでした。ここは生ヘッダーごと _raw/ に落としてあるので、後から数え直せます。とにかく、実額はコンソールの残高でしか追えないんですよね。

ここで数え方の話をします。コンソールの残高はセント単位に丸められるので、1回叩いただけでは単価が出ません。$0.005 を消費しても、減り方は $0.01 に見えるんですよね。2回叩いて累計 $0.01 まで来て、ようやく料金表の $0.005 と整合します。ただし丸めが残るので、2件で言えるのは「表の値と矛盾しない」まで。幅を潰したいなら10回叩いて $0.05 を見るのが早いです。僕は2回で止めました。

分かったことは2つです。ひとつは、著者やメディアといった関連データ(includes)が課金対象じゃないこと。取得した2件にぶら下がっていた1件と2件は、請求に乗っていませんでした。

もうひとつが、いちばん確かめたかったところで。僕が読みたい Article(長文記事)付きの投稿は、料金表に行が存在しないんですよね。Read 表12行・Write 表16行、全部見ても無い。つまり表を読んだだけじゃ、自分が払う額が分からない。それが叩いてみたら、通常の Post 読み取りと同じ $0.005 でした。拍子抜けではあるんですが、通常のポストと同じ金額で大量の文章情報が取れるってのはうれしいですね!

ここまでに出てきた金額を、いちど並べておきます。

何にいくらどこで分かるか
投稿1件の読み取り$0.005料金表の Read の行
Article 付きの投稿$0.005叩いて実測(料金表に行が無い)
includes(著者・メディア)$02件を突き合わせて確認
画像の URL(includes.media。添付も Article 本文中も)$0写真4枚の投稿を2回取って、累計が投稿ぶんしか動かないのを確認
クレジットの最低購入額$5 からコンソール(料金ページに記載なし)
まとめ取りの課金単位不明1件ずつしか叩いていない

変わったのは、「あとで読む」が消えたこと

一文で言い切ると、払った金額が何かを変えたわけじゃないんですよね。$0.005 はただの入場料です。変わったのは、自分の環境に繋いだことのほうでした。

いま X の URL を Claude Code に渡すと、「これ取っておいて」で本文が手元に落ちてくるようになっています。最初に挙げた @HayattiQ さんの投稿も、実はこの経路で手元に落ちてきたものだったりします。

正直に計算すると、月1本の作業を自動化するのに CLI と skill を書いたわけで、費用対効果で見るとゴミですね。時間が浮いた、という話でもない。消えたのは「あとでやろう」のほうです。これまでは、X の中にある情報に対して「気が向いたらコピペする」以外の触り方を持っていなかったので、取りにいく発想がそもそも無かった。それが URL を渡すだけになると、取りにいこうと思えるようになります

最初の一歩として渡すのはひとつだけです。CLI を書けとは言いません。まず1件だけ、正規ルートで取ってみてください。表に載っていない自分のユースケースの単価は、そこで初めて見えてきます。

ちなみに正規のルートはもう一本あって、Grok(xAI)から X を検索させる道です。そっちは X API のクレジットとは別の勘定、別の課金体系になります。ただ、値段の付け方が 2026-09-21 に変わるので、そこも含めて別記事にまとめました。課金して実際に叩いています!

ではまた!

付録:article のキーは、公式に定義が無いので実測を置いておきます

本文で触れたとおり、article のサブフィールドは公式ドキュメントに定義がありません(2026-09-09 時点)。1件ぶんのレスポンスから読み取れたものを並べておきます。字数はその投稿のものです。

キー中身
article.plain_text本文の全文(実測 1,647 字)
article.preview_text冒頭の抜粋(実測 111 字)
article.title記事のタイトル(実測 39 字)
article.entities本文中の構造化要素。コードブロックが code 配列で取れます
article.media_entities本文中のメディアの ID。実体は includes.media 側に入る

指定しても返ってこなかったものも2つあります。article_titletweet.fields の enum にありますが返らず、タイトルは article.title のほうに入ります。note_tweet は280字を超える長文投稿のためのフィールドで、Article とは別機能なので、Article 付きの投稿では使われません。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。
エンジニア募集中!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です