Twitter APIのexpansionsとツイートの投稿者
公式X APIでは、投稿はIDとテキストだけで返ってきます。expansions=author_id を付けると投稿者のプロフィールが別の includes ブロックに入り、2026年11月22日からは、この方法で返された投稿者1人ごとに$0.010が課金されます。
要点: リクエストに expansions=author_id と user.fields を加え、各投稿の author_id を includes.users のユーザーと突き合わせます。2026年11月22日からは、投稿者つきの投稿1件が最大$0.015かかります。Sorsa APIはすべてのツイートに投稿者の完全なプロフィールを含めます。POST /tweet-info-bulk は1リクエストで100ツイートを、1,000件あたり$0.014から読み取り、100回分の無料リクエストで最初の1万件をまかなえます。
- エンドポイント
POST /tweet-info-bulk- 1ページの件数
- 1リクエストあたり100ツイート
- 料金
- 1,000件あたり$0.014から
#Twitter APIのexpansionsとは、何を返すか
expansionは公式X API v2のリクエストパラメーターで、投稿者、写真、引用投稿といった関連オブジェクトをレスポンスに加えます。expansionがない投稿の取得では、id、text、edit_history_tweet_ids の3つのフィールドしか返りません。投稿者は含まれず、投稿者のIDすらありません。
expansions=author_id を指定すると、各投稿に author_id が加わり、レスポンスには投稿者1人につき1件の includes.users リストが加わります。既定ではその項目に入るのは id、name、username だけです。自己紹介、フォロワー数、アバターなどそれ以外は、user.fields で指定する必要があります。
次のリストは、開発者がよく使う投稿のexpansionと、2026年11月22日から適用されるX APIの料金での費用です。ユーザーオブジェクトは、一緒に取得した投稿の2倍の費用がかかります。
| Expansion | includes に加わるもの | 公式X API、11月22日以降のオブジェクト単価 |
|---|---|---|
author_id | 投稿の投稿者 | $0.010 |
referenced_tweets.id | 引用、返信先、リポスト元の投稿 | $0.005 |
referenced_tweets.id.author_id | その投稿の投稿者 | $0.010 |
in_reply_to_user_id | 返信先のアカウント | $0.010 |
entities.mentions.username | メンションされた各アカウント | $0.010 |
attachments.media_keys | 写真、動画、GIFそれぞれ | $0.005 |
attachments.poll_ids | 投票 | $0.005 |
geo.place_id | タグ付けされた場所 | $0.005 |
author_idincludesに加わるもの- 投稿の投稿者
- 公式X API、11月22日以降のオブジェクト単価
- $0.010
referenced_tweets.idincludesに加わるもの- 引用、返信先、リポスト元の投稿
- 公式X API、11月22日以降のオブジェクト単価
- $0.005
referenced_tweets.id.author_idincludesに加わるもの- その投稿の投稿者
- 公式X API、11月22日以降のオブジェクト単価
- $0.010
in_reply_to_user_idincludesに加わるもの- 返信先のアカウント
- 公式X API、11月22日以降のオブジェクト単価
- $0.010
entities.mentions.usernameincludesに加わるもの- メンションされた各アカウント
- 公式X API、11月22日以降のオブジェクト単価
- $0.010
attachments.media_keysincludesに加わるもの- 写真、動画、GIFそれぞれ
- 公式X API、11月22日以降のオブジェクト単価
- $0.005
attachments.poll_idsincludesに加わるもの- 投票
- 公式X API、11月22日以降のオブジェクト単価
- $0.005
geo.place_idincludesに加わるもの- タグ付けされた場所
- 公式X API、11月22日以降のオブジェクト単価
- $0.005
単価は、Xの2026年10月23日付のexpansions課金に関する通知(新しいタブで開きます)に基づきます。通知には、expansionで返されるオブジェクトは「直接取得と同じ、そのリソースの標準のPPU料金」で課金されると書かれています(原文は "at the standard PPU rate for that resource, the same as direct lookups")。それ以前は、投稿に上乗せされる費用はありませんでした。
#Sorsa APIで、ツイートと投稿者を1回の呼び出しで取得する
Twitter(X)API兼スクレイピングツールであるSorsa APIは、すべてのツイートに user オブジェクトを含めて返します。投稿者の完全な公開プロフィール19フィールドが、追加料金なしで入っています。expansionを足す必要も、別のリストを結合する必要も、投稿者ごとの課金もありません。APIキーを付けた1回のリクエストでツイートが返り、各ツイートがすでに書いた人を知っています。
-
キーを取得する。 登録して、ダッシュボードからAPIキーをコピーします。Xの開発者アカウントもOAuthも不要です。
-
最大100件のツイートのリンクまたはIDを送る。
POST /tweet-info-bulk(新しいタブで開きます) はツイートのURLまたはIDだけのリストを受け取り、ページ送りなしで1回のレスポンスにまとめて返します。Terminal curl -X POST "https://api.sorsa.io/v3/tweet-info-bulk" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"tweet_links": ["1849212213712385091", "https://x.com/kai_builds_tools/status/1849212213712385092"]}'Response200 OK { "tweets": [ { "id": "1849212213712385091", "full_text": "Shipped the new export queue today.", "created_at": "2026-10-24T09:12:44Z", "likes_count": 214, "retweet_count": 31, "view_count": 18402, "user": { "id": "1592041833471827968", "username": "kai_builds_tools", "display_name": "Kai Builds", "description": "Data tooling for small teams.", "followers_count": 1840, "followings_count": 312, "tweets_count": 2291, "verified": false, "created_at": "2022-11-14T08:03:10Z", "location": "Lisbon", "profile_image_url": "https://pbs.twimg.com/profile_images/1/kai.jpg" } } ] } -
投稿者を各ツイートから直接読む。 プロフィールは
tweet["user"]の下にあるので、ツイートをループするだけで済みます。import requests URL = "https://api.sorsa.io/v3/tweet-info-bulk" HEADERS = {"ApiKey": "YOUR_API_KEY"} def tweets_with_authors(ids): for start in range(0, len(ids), 100): batch = ids[start:start + 100] r = requests.post(URL, headers=HEADERS, json={"tweet_links": batch}) r.raise_for_status() for tweet in r.json()["tweets"]: author = tweet["user"] yield (tweet["id"], author["username"], author["followers_count"], tweet["full_text"])
403はキーがない、またはリクエストを使い切ったことを意味します。429は1秒間に20リクエストを超えたことを意味するので、少し待って再試行してください。失敗したリクエストに課金されることはありません。
同じ user オブジェクトは、検索、タイムライン、返信、引用から得たツイートにも付いてきます。POST /search-tweets(新しいタブで開きます) は1ページあたり約20件のツイートを投稿者つきで返します。Xの検索演算子を使い、2006年までさかのぼって公開投稿を検索でき、次のページ用の next_cursor を、カーソルが空になるまで返します。
#公式X APIで、投稿と投稿者を突き合わせる
公式X APIで投稿と投稿者を突き合わせるには、includes.users をユーザーIDをキーとした辞書にして、各投稿の author_id を引きます。Xのexpansionsガイド(新しいタブで開きます)によると、includes のオブジェクトには順序の情報がなく、2つのリストをつなぐのはIDだけです。
curl -G "https://api.x.com/2/tweets" \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
--data-urlencode "ids=1849212213712385091,1849212213712385092" \
--data-urlencode "expansions=author_id" \
--data-urlencode "user.fields=description,public_metrics,profile_image_url"
{
"data": [
{
"id": "1849212213712385091",
"text": "Shipped the new export queue today.",
"author_id": "1592041833471827968",
"edit_history_tweet_ids": ["1849212213712385091"]
},
{
"id": "1849212213712385092",
"text": "Next up: retries with backoff.",
"author_id": "1592041833471827968",
"edit_history_tweet_ids": ["1849212213712385092"]
}
],
"includes": {
"users": [
{
"id": "1592041833471827968",
"name": "Kai Builds",
"username": "kai_builds_tools",
"description": "Data tooling for small teams.",
"public_metrics": {"followers_count": 1840, "following_count": 312}
}
]
}
}
投稿は2件、投稿者は1人です。includes.users は、投稿ごとではなく、レスポンスごとに投稿者を1回だけ載せます。このため、リストが data より短くなることがよくあり、位置で参照したり、includes["users"]["username"] を単一のオブジェクトのように読んだりすると壊れます。次のループは、最近の検索結果をページごとにたどり、ページをまたいで1つの投稿者辞書を保持します。
import requests
URL = "https://api.x.com/2/tweets/search/recent"
HEADERS = {"Authorization": "Bearer YOUR_BEARER_TOKEN"}
params = {
"query": "from:kai_builds_tools",
"max_results": 100,
"expansions": "author_id",
"user.fields": "description,public_metrics,profile_image_url",
}
authors, rows = {}, []
while True:
page = requests.get(URL, headers=HEADERS, params=params).json()
for user in page.get("includes", {}).get("users", []):
authors[user["id"]] = user
for post in page.get("data", []):
author = authors.get(post["author_id"], {})
rows.append((post["id"], author.get("username"), post["text"]))
token = page.get("meta", {}).get("next_token")
if not token:
break
params["next_token"] = token
投稿者には .get() を使ってください。凍結または公開停止されたアカウントは、投稿が data に残っていても includes から欠けることがあり、その場合は欠けた分がレスポンスの errors 配列に載ります。
リツイートや引用の投稿者
リポストや引用は別の投稿を指す投稿であり、その author_id は元の投稿者ではなく、リポストまたは引用した人です。元の投稿者も取得するには、author_id、referenced_tweets.id、referenced_tweets.id.author_id の3つのexpansionを指定します。元の投稿は includes.tweets に、その投稿者はリポストした人と並んで includes.users に入るので、referenced_tweets[0].id をたどり、次にその投稿の author_id をたどって結合します。11月22日以降は、このリポスト1件で投稿2件とユーザー2人が課金され、$0.030になります。
Sorsa APIでは、リポストされたツイートは retweeted_status、引用されたツイートは quoted_status として返り、どちらも自分の user を内部に持つ完全なツイートです。
#2026年11月22日からのexpansionsの費用
2026年11月22日から、expansionが加えるすべてのオブジェクトは、直接の読み取りと同じように課金されます。ユーザーは1人$0.010、投稿、写真、動画、投票、場所は1件$0.005です。そのため、投稿者つきで読む投稿は最大$0.015となり、これまでの$0.005の3倍です。投稿ごとに写真を1枚加えると最大$0.020、引用投稿とその投稿者まで加えると$0.035に達します。
Xは、UTCの24時間の日単位で重複排除します。従量課金の料金ページ(新しいタブで開きます)によれば、同じ日に再取得したリソースには再び課金されません。その日にあなたの投稿を50件書いたユーザーも、課金は1回です。したがって、投稿者200人による1,000件の投稿は、投稿分$5.00と投稿者分$2.00で、合計$7.00です。投稿者1,000人による1,000件の投稿なら$15.00になります。重複排除はUTCの午前0時にリセットされ、Xはこれを「ソフトな保証」と呼んでいます。
Sorsa APIでは、ツイートに何が含まれていても価格は変わりません。IDによるツイートの取得は、投稿者、引用投稿、メディアのリンクを含めて1,000件あたり$0.014からで、検索結果は1,000件あたり$0.07からです。公式X APIで投稿者つきの1,000件が$15.00であるのに比べると、約1,000分の1です。
| 読み取る内容(1,000投稿あたり) | Sorsa API | 公式X API(11月22日以降) |
|---|---|---|
| 投稿のみ | $0.014から | $5.00 |
| 投稿者つきの投稿 | $0.014から | 最大$15.00 |
| さらに写真または動画1つずつ | $0.014から | 最大$20.00 |
| さらに引用投稿とその投稿者 | $0.014から | 最大$35.00 |
投稿のみ
- Sorsa API
- $0.014から
- 公式X API(11月22日以降)
- $5.00
投稿者つきの投稿
- Sorsa API
- $0.014から
- 公式X API(11月22日以降)
- 最大$15.00
さらに写真または動画1つずつ
- Sorsa API
- $0.014から
- 公式X API(11月22日以降)
- 最大$20.00
さらに引用投稿とその投稿者
- Sorsa API
- $0.014から
- 公式X API(11月22日以降)
- 最大$35.00
計算ツールでは、使うexpansionごとに、1か月分の投稿の費用を見積もれます。すべての投稿者を新規として数えるため、金額は上限側です。重複する投稿者を選ぶと、重複排除の効果を確認できます。
公式X APIでは拡張ごとに別料金がかかります。Sorsa APIでは、投稿者、引用投稿、メディアのリンクがツイートに含まれます。
知っておきたいこと
Xの従量課金プランは、月間300万投稿の読み取りで止まります。それを超えると、公式X APIは月約$42,000からのEnterprise契約になります。Sorsa APIでは、プランが大きくなるほど1,000ツイートあたりの料金が下がり、投稿者はどのプランでもすべてのツイートに含まれます。
#投稿者がツイートの中になくなった理由
かつて、投稿者はツイートの一部でした。v1.1の形式では、すべてのツイートオブジェクトに投稿者のプロフィールを持つ user オブジェクトが含まれていて、twarcのドキュメント(新しいタブで開きます)の言葉を借りれば、1つのツイートだけで完結していました。2020年に公開されたAPIのバージョン2は、各オブジェクトを少数の既定フィールドに絞り、関連オブジェクトを includes に移しました。そこへはexpansionを通じてしか届きません。
これまでは、この分離で増えるのはコードの手間だけで、お金はかかりませんでした。expansionで返されるオブジェクトは利用量にカウントされず、expansionを使えば2回目のリクエストを省けたからです。2026年10月の通知で、お金の部分が変わりました。11月22日からは、includes.users から結合する投稿者は、単独で取得した場合と同じ扱いで課金されます。
この点で、Sorsa APIのツイートはv1.1のものに似ています。user がツイートの中にあります。tweet["user"]["screen_name"] を読むv1.1向けのコードは、キー名を username に変えるだけで済みます。v2のコードベースの残りの部分をエンドポイントごとに対応づけたものは、Twitter/X APIからの移行のガイドにあります。
#Sorsa APIのツイートに付く投稿者フィールド
Sorsa APIの各ツイートは、リクエストの指定なしで、user の下に19の投稿者フィールドを持っています。次の表は、ほとんどのコードで必要になるものを、user.fields に列挙する公式X APIの名前と対応づけたものです。
Sorsa APIの user フィールド | 公式X APIの user.fields の名前 |
|---|---|
username | username |
display_name | name |
description | description |
followers_count | public_metrics.followers_count |
followings_count | public_metrics.following_count |
tweets_count | public_metrics.tweet_count |
profile_image_url | profile_image_url |
created_at | created_at |
location | location |
verified | verified |
protected | protected |
pinned_tweet_ids | pinned_tweet_id |
bio_urls | entities.description.urls |
username- 公式X APIの
user.fieldsの名前 username
- 公式X APIの
display_name- 公式X APIの
user.fieldsの名前 name
- 公式X APIの
description- 公式X APIの
user.fieldsの名前 description
- 公式X APIの
followers_count- 公式X APIの
user.fieldsの名前 public_metrics.followers_count
- 公式X APIの
followings_count- 公式X APIの
user.fieldsの名前 public_metrics.following_count
- 公式X APIの
tweets_count- 公式X APIの
user.fieldsの名前 public_metrics.tweet_count
- 公式X APIの
profile_image_url- 公式X APIの
user.fieldsの名前 profile_image_url
- 公式X APIの
created_at- 公式X APIの
user.fieldsの名前 created_at
- 公式X APIの
location- 公式X APIの
user.fieldsの名前 location
- 公式X APIの
verified- 公式X APIの
user.fieldsの名前 verified
- 公式X APIの
protected- 公式X APIの
user.fieldsの名前 protected
- 公式X APIの
pinned_tweet_ids- 公式X APIの
user.fieldsの名前 pinned_tweet_id
- 公式X APIの
bio_urls- 公式X APIの
user.fieldsの名前 entities.description.urls
- 公式X APIの
残りの6つは、id、favourites_count、media_count、profile_background_image_url、can_dm、possibly_sensitive です。IDは文字列、日付はISO 8601で返ります。ツイート、プロフィールなどのオブジェクトに含まれる項目の一覧は、Twitter APIで取得できるデータのガイドにあります。
出発点がツイートIDのリストなら、ツイートIDの再取得(rehydrate)のガイドで、1リクエスト100件のIDで数百万件のリストを扱う方法を解説しています。
#最初のツイートを投稿者つきで読み取る
公式X APIでは、投稿の投稿者はexpansionです。結合する別のリストが必要で、2026年11月22日からは、投稿$0.005に加えて投稿者ごとに$0.010がかかります。ツイートを投稿者つきでまとめて取得するなら、Sorsa APIを使ってください。POST /tweet-info-bulk は1リクエストで100ツイートを、それぞれ投稿者の完全なプロフィールつきで、1,000件あたり$0.014から返します。レートは全プラン毎秒20リクエストです。
Sorsa APIがXのログイン情報を求めることはないので、ご自身のアカウントが危険にさらされることはありません。設計上、読み取り専用でもあります。投稿には公式X APIを組み合わせてください。100回分の無料リクエストで、最初の1万ツイートを投稿者つきで読み取れます。
#よくある質問
公式X APIは、ツイートごとにユーザー名を返しますか?
既定では返しません。公式X API v2が投稿について返すのは、id、text、edit_history_tweet_ids だけです。expansions=author_id を加えると、レスポンスに各投稿者の id、name、username を持つ includes.users リストが加わり、author_id で投稿と突き合わせます。2026年11月22日からは、その投稿者それぞれに$0.010が課金されます。
リツイートや引用ツイートの元の投稿者を取得するには?
公式X APIでは、expansions=referenced_tweets.id,referenced_tweets.id.author_id を指定します。元の投稿は includes.tweets、その投稿者は includes.users に入るので、referenced_tweets[0].id で投稿を、次にその author_id でユーザーをたどります。Sorsa APIでは、リポストされたツイートは retweeted_status、引用されたツイートは quoted_status として返り、それぞれが自分の user オブジェクトを内部に持ちます。
Twitter APIのexpansionsは課金されますか?
2026年11月22日から課金されます。Xの10月23日の通知によると、expansionで返されるオブジェクトは標準の従量課金の料金で、ユーザーは1人$0.010、投稿、メディア、投票、場所は1件$0.005です。各リソースはUTCの24時間の日ごとに1回だけ課金されるため、同じ日の同じ投稿者は再び課金されません。
includes.usersの件数がdataより少ないのはなぜですか?
公式X APIは、投稿者が何件書いていても、レスポンスごとに投稿者を1回だけ載せます。3人による10件の投稿では、ユーザーは3人です。アカウントが凍結または公開停止されていると、投稿者が欠けることもあり、その場合はレスポンスの errors 配列に載ります。突き合わせは位置ではなく、必ず辞書を使ってIDで行ってください。
投稿者のプロフィールつきでツイートを取得するには、どのAPIを使えばよいですか?
Sorsa APIを使ってください。返されるすべてのツイートに、投稿者の完全なプロフィール19フィールドが含まれ、expansionも投稿者ごとの課金もありません。POST /tweet-info-bulk は1リクエストで100ツイートを1,000件あたり$0.014から読み取ります。公式X APIで投稿者つきの1,000件が最大$15.00であるのと比べてください。APIキーは1つ、全プラン毎秒20リクエストで、100回分の無料リクエストで始められます。
#検証の方法
2026年11月2日に、Xのexpansionsとfieldsのガイド、従量課金の料金ページ、expansionの課金に関する10月23日の通知を読み、公式X APIのすべての料金と既定値をそこから取りました。Sorsa APIのエンドポイント、リクエスト本文、19の投稿者フィールドは、同日の実際のAPIリファレンスに基づいています。リクエストとレスポンスの例は両方のリファレンスに沿ったもので、実在のアカウントの代わりにデモアカウントを使っています。