Twitter検索APIでツイートを検索する方法
APIでツイートを検索するには、キーワードとXの検索演算子を組み合わせたクエリを検索エンドポイントに送り、一致したツイートをJSONのページで受け取ります。公式X APIの料金は、結果1,000件あたり$5.00です。
要点: X自身の検索は2つのエンドポイントに分かれています。直近検索は過去7日間を、全アーカイブ検索は2006年3月までをカバーし、どちらも開発者アカウントとBearerトークンが必要です。キー1つで検索するなら、Sorsa APIの POST /search-tweets が使えます。1リクエストで約20ツイート、2006年までさかのぼれて、1,000件あたり$0.07からです。まずは100回分の無料リクエストで試せます。
- エンドポイント
POST /search-tweets- 1ページの件数
- 1リクエストあたり約20ツイート
- 料金
- 1,000件あたり$0.07から
#Twitter検索APIの仕組み
Twitter検索APIとは、公開ツイートに対するXの検索を、あなたに代わって実行するエンドポイントです。"vector database" lang:en min_faves:20 のようなクエリを1つ送ると、一致したツイートのページが返ります。各ツイートには、本文、日付、各種カウント、投稿者が含まれ、次のページを取得するカーソルも付きます。
コードを書く前にクエリを試すなら、無料のTwitter高度な検索ツールで実行できます。最初の20件の一致投稿が表示され、設定したフィルターはすべて演算子としてクエリに書き込まれるので、そのままリクエストに貼り付けられます。
返ってくる内容は、3つの設定で決まります。クエリは、語句、アカウント、言語、メディア、エンゲージメントでツイートを選びます。並び順は、エンゲージメントの高い一致から並べるTop(人気順)か、新しい順に並べるLatest(最新順)です。期間の指定は、Xのウェブ構文ではクエリ内の since: と until: に書き、公式X APIでは別の時間パラメーターに書きます。
公式X APIは、検索を2つのエンドポイントに分けています(Xの検索ドキュメント(新しいタブで開きます))。GET /2/tweets/search/recent は過去7日間をカバーし、1リクエストで10〜100件の投稿を返します。GET /2/tweets/search/all は2006年3月までさかのぼり、最大500件を返します。どちらも、承認された開発者アカウント、ProjectとApp、Bearerトークンが必要で、返した投稿1件ごとに$0.005が課金されます。
#Sorsa APIで4ステップでツイートを検索する
コードからツイートを検索するなら、Twitter(X)API兼スクレイピングツールであるSorsa APIが使えます。結果は1,000件あたり$0.07から、2006年までの任意の日付を指定でき、全プラン毎秒20リクエストです。開発者アカウントとOAuthの代わりに、必要なのは ApiKey ヘッダー1つです。x.comの検索ボックスと同じクエリ構文を読み取り、あなたのXアカウントには一切触れません。
-
キーを取得します。 登録して、ダッシュボードからAPIキーをコピーします。100回分の無料リクエストは、すでに付いています。
-
クエリを書きます。 x.comで入力するのと同じように書きます。語句、
"exact phrases"、from:、lang:、min_faves:、since:が使えます。 -
リクエストを送ります。 クエリをJSONボディに入れて
POST /search-tweets(新しいタブで開きます)にPOSTします。新しいツイートから順に取得するなら"order": "latest"、Topなら"popular"を指定します。Terminal curl -X POST "https://api.sorsa.io/v3/search-tweets" \ -H "ApiKey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "\"vector database\" lang:en min_faves:20", "order": "latest"}'Response200 OK { "tweets": [ { "id": "2116173807613027825", "full_text": "Benchmarked three vector databases on 40M embeddings.", "created_at": "2026-10-30T14:22:07Z", "lang": "en", "likes_count": 214, "retweet_count": 37, "reply_count": 19, "quote_count": 6, "view_count": 18450, "bookmark_count": 92, "is_reply": false, "is_quote_status": false, "conversation_id_str": "2116173807613027825", "entities": [], "user": { "id": "1620350095193014349", "username": "indexlab_notes_daily", "display_name": "Index Lab Notes", "followers_count": 8312, "verified": false, "created_at": "2023-01-31T09:15:42Z" } } ], "next_cursor": "DAADDAABCgABHV3t2nWAJ8kKAAIdXcTm0Zvw" } -
カーソルをたどります。 どのツイートにも投稿者のプロフィール全体が含まれるので、別途問い合わせる必要はありません。次のページは、同じボディに
next_cursorを入れて送り返します。カーソルのないレスポンスが返ったら止めてください。
403はキーがないかリクエストを使い切ったことを、401はキーが誤っていることを示します。429は1秒間に20リクエストを超えたことを示すので、1秒待って再送してください。失敗したリクエストに課金されることはありません。
下の欄に自分のクエリを貼り付けると、チェックしたうえで、curl、Python、Node.jsのリクエストを生成します。JSONボディ内の引用符はエスケープ済みです。このチェッカーは、ウェブ構文では使わない公式X APIの演算子名も指摘します。
問題は見つかりません。このクエリはXのWeb検索の構文で書かれており、 POST /search-tweets はそのまま受け付けます。
curl -X POST "https://api.sorsa.io/v3/search-tweets" \
-H "ApiKey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "\"vector database\" lang:en min_faves:20", "order": "latest"}'
import requests
r = requests.post(
"https://api.sorsa.io/v3/search-tweets",
headers={"ApiKey": "YOUR_API_KEY"},
json={"query": '"vector database" lang:en min_faves:20',
"order": "latest"},
timeout=30,
)
page = r.json()
for t in page["tweets"]:
print(t["user"]["username"], t["full_text"])
print(page.get("next_cursor"))
const res = await fetch("https://api.sorsa.io/v3/search-tweets", {
method: "POST",
headers: { ApiKey: "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
query: '"vector database" lang:en min_faves:20',
order: "latest",
}),
});
const page = await res.json();
for (const t of page.tweets) console.log(t.user.username, t.full_text);
console.log(page.next_cursor);
1リクエストで約20ツイートが返るため、1,000件の結果には約50リクエストが必要です。Sorsa APIなら最安$0.07、公式X APIでは$5.00です。
クエリをチェックして、リクエストに変換しました。実行する前に、YOUR_API_KEYを自分のキーに置き換えてください。
#コードで動くクエリの書き方
/search-tweets のクエリは、x.comの検索ボックスに入力するのと同じ文字列です。そのため、ブラウザーで組み立てたものを、そのままリクエストに貼り付けられます。開発者がつまずく問題のほとんどは、7つのルールでカバーできます。
- スペースはAND、
ORは大文字、先頭の-は語句や演算子の除外、丸括弧はグループ化を表します。例:(rust OR golang) -hiring - 完全一致のフレーズは二重引用符で囲みます。生のJSON文字列の中では、引用符にバックスラッシュが必要です(
"\"vector database\"")。PythonとNode.jsでは、辞書やオブジェクトを渡せばライブラリがエスケープしてくれます。 - ハッシュタグ、キャッシュタグ、メンションは書いたとおりに入れます。
#buildinpublic、$NVDA、@acme_cloud_statusです。クエリはJSONボディで送るので、URLエンコードは不要です。 - 日付はクエリに書きます。
since:2026-10-01はその日を含み、until:2026-11-01はその日の手前までで、どちらもUTCです。 - エンゲージメントの下限は
min_faves:、min_retweets:、min_replies:です。頭にマイナスを付けると下限が上限に変わります(-min_faves:1000)。 - ネイティブのリツイートは、
include:nativeretweetsを付けない限り除外されます。-filter:repliesを付けると、リプライ以外のトップレベルの投稿だけが残ります。 - 1つのクエリに入る演算子は約22個までです。それより長いアカウントやキーワードのリストは、複数のクエリに分けてください。
チームがよく検索する内容のほとんどは、5つのパターンでカバーできます。どれも query フィールドにそのまま貼り付けられます。
# Mentions of a brand, without its own posts
("acme cloud" OR @acme_cloud_status) -from:acme_cloud_status
# The most liked posts on a topic
"vector database" min_faves:100 -filter:replies lang:en
# One account's posts on a subject in October
from:acme_cloud_status outage since:2026-10-01 until:2026-11-01
# Posts that link to a site
url:github.com rust -filter:replies
# Images under a hashtag
#buildinpublic filter:images
各演算子の癖と例は、Twitterの検索演算子の一覧にすべて載っています。
#全ページを取得して、検索を回し続ける
1ページより多く収集するには、直前のレスポンスの next_cursor を入れた同じボディをもう一度送り、カーソルのないレスポンスが返ったら止めます。1ページは約20ツイートで、件数にはばらつきがあります。ページが短くても検索の終わりを意味せず、終わりを示すのはカーソルがなくなったときだけです。
下のループは、届いたツイートを1件ずつJSON Linesファイルに書き込み、保存済みのIDは飛ばします。ページ数の上限を設けてあるので、広すぎるクエリでリクエストを使い込む心配はありません。
import json
import requests
API = "https://api.sorsa.io/v3/search-tweets"
HEADERS = {"ApiKey": "YOUR_API_KEY"}
def search(query, order="latest", max_pages=50):
body = {"query": query, "order": order}
for _ in range(max_pages):
r = requests.post(API, json=body, headers=HEADERS, timeout=30)
r.raise_for_status()
page = r.json()
yield from page.get("tweets", [])
cursor = page.get("next_cursor")
if not cursor:
break
body["next_cursor"] = cursor
seen = set()
with open("tweets.jsonl", "w", encoding="utf-8") as f:
for t in search('"vector database" lang:en min_faves:20'):
if t["id"] not in seen:
seen.add(t["id"])
f.write(json.dumps(t) + "\n")
検索を回し続けるには、同じループをタイマーで繰り返します。最新のツイートを取得し、前回保存した最大のIDを since_id: に指定して、カーソルが尽きるまで読み、新しい最大のIDを保存します。新しい投稿がなければ、確認にかかるのは1リクエストだけです。そのため、投稿の少ないクエリを頻繁に確認しても、費用は小さく済みます。
import time
newest = None
while True:
query = '"vector database" lang:en'
if newest:
query += f" since_id:{newest}"
fresh = list(search(query))
if fresh:
newest = max(fresh, key=lambda t: int(t["id"]))["id"]
print(len(fresh), "new tweets")
time.sleep(300)
検索はポーリングで動きます。購読できるストリームはありません。アラート、スケジュール、Slackやメールへの通知まで含めたパイプライン全体は、Twitterのリアルタイム監視のガイドで構築します。リトライや並列検索は、PythonでTwitter APIのガイドで追加します。
知っておきたいこと
ツイートを収集したり数えたりするときは、必ず
"order": "latest"を使ってください。一致するすべてのツイートを、新しいものから順にさかのぼります。Topタブに相当する"popular"は、エンゲージメントの高い一致だけを返すので、同じクエリでもTopを2回実行すると、異なる結果になることがあります。
#ハッシュタグでツイートを検索する
ハッシュタグで検索するには、タグを入力するときと同じ形で、#buildinpublic のようにクエリへ入れます。ハッシュタグとして書かれているツイートに、大文字小文字を問わず一致し、ほかのどの演算子とも組み合わせられます。
タグなしで同じ語句を書く人もいるなら、OR で通常の語句も加えます。(#buildinpublic OR "build in public") min_faves:10 -filter:replies lang:en のようにします。複数のタグは OR でつなぎます。株式や暗号資産のシンボルには、$NVDA のようなキャッシュタグを使います。
Sorsa APIでは、# がJSONボディにそのまま入ります。公式X APIのGETリクエストでは、%23 に変換する必要があります。エンコードしていない # はURLの終わりを意味するので、サーバーにはタグが届かないからです。ハッシュタグの推移を数えるには、since: と until: で1日ごとにLatestの検索を実行し、日ごとに返るツイートの数を数えます。
#目的の検索に合うエンドポイントを選ぶ
キーワード検索は、Sorsa APIでツイートを見つける5つの方法のうちの1つです。どのエンドポイントが適切かは、何を起点にするかで決まります。語句、1つのアカウント、アカウントの集合、あるいは人そのものです。
残りの4つは、それぞれ別の起点から読み取ります。POST /mentions(新しいタブで開きます) は、ハンドルを1つ受け取り、そのアカウントにメンションしたツイートを返します。いいね、リプライ、リツイート、日付のフィルターをボディで指定できます。POST /search-users(新しいタブで開きます) は、名前や自己紹介が語句に一致するアカウントを探します。POST /user-tweets(新しいタブで開きます) は、1つのアカウント自身のタイムラインを1リクエストあたり約20ツイートで読み取ります。Xリストのメンバーの投稿は、GET /list-tweets(新しいタブで開きます) から1つのフィードとして返ります。そのため、最大5,000アカウントのリストを、1ページにつき1リクエストで監視できます。
ブランドのチームは、たいてい2つを組み合わせます。人々が製品について語る内容には /search-tweets、人々がそのアカウントに向けて語る内容には /mentions です。後者は、TwitterメンションAPIのガイドで解説しています。
#ツイート検索にかかる費用
Sorsa APIでは、検索結果は1,000ツイートあたり$0.07からです。1リクエストで約20ツイートが返り、中身にかかわらず1リクエストとして課金されます。公式X APIは、返した投稿1件ごとに$0.005、つまり1,000件あたり$5.00を課金します(Xの料金表(新しいタブで開きます))。
公式X API
$5,000
検索結果100万件の場合
1投稿$0.005
Sorsa API
$70から
検索結果100万件の場合
1,000件あたり$0.07から
71分の1のコスト
投稿者もあわせて取得すると、公式の料金は上がります。2026年11月22日から、Xはエクスパンション経由で返される各ユーザーに$0.010を課金します(Xの10月23日のお知らせ(新しいタブで開きます))。そのため、投稿者がすべて異なる結果1,000件は、$15.00になることがあります。Sorsa APIは、どのツイートにも投稿者のプロフィール全体を、追加料金なしで含めています。
量にも上限があります。従量課金は月間300万件の投稿読み取りで止まり、それを超える分は、XはEnterprise契約しか販売していません。Sorsa APIには300万件の上限がなく、プランは月間1,000万リクエストまで拡張できます。100回分の無料リクエストで約2,000件の検索結果を、カードなしで取得できます。公式の料金は、X APIの料金の解説にすべて載っています。
#公式X APIの検索との比較
公式X APIの検索は、結果1,000件あたりでSorsa APIの約71倍の費用がかかります。直近検索は過去7日間しか見られず、アプリあたり15分に450リクエストまでです。下の表で3つの検索エンドポイントを並べて比較します。公式の制限はXのレート制限表(新しいタブで開きます)によります。
Sorsa APIの /search-tweets | X 直近検索 | X 全アーカイブ検索 | |
|---|---|---|---|
| 対象期間 | 2006年3月まで | 過去7日間 | 2006年3月まで |
| 1リクエストの結果数 | 約20 | 10〜100 | 10〜500 |
| レート制限 | キーあたり毎秒20リクエスト | アプリあたり15分に450リクエスト | 毎秒1リクエスト、15分に300リクエスト |
| 結果1,000件あたりの料金 | $0.07から | $5.00 | $5.00 |
| 投稿者のプロフィール | すべてのツイートに含まれる | 2026年11月22日から1人$0.010で課金 | 2026年11月22日から1人$0.010で課金 |
| クエリ構文 | x.comのウェブ検索 | v2演算子、512文字 | v2演算子、1,024文字 |
| セットアップ | APIキー1つ | 開発者アカウント、App、Bearerトークン | 開発者アカウント、App、Bearerトークン |
対象期間
- Sorsa APIの
/search-tweets - 2006年3月まで
- X 直近検索
- 過去7日間
- X 全アーカイブ検索
- 2006年3月まで
- Sorsa APIの
1リクエストの結果数
- Sorsa APIの
/search-tweets - 約20
- X 直近検索
- 10〜100
- X 全アーカイブ検索
- 10〜500
- Sorsa APIの
レート制限
- Sorsa APIの
/search-tweets - キーあたり毎秒20リクエスト
- X 直近検索
- アプリあたり15分に450リクエスト
- X 全アーカイブ検索
- 毎秒1リクエスト、15分に300リクエスト
- Sorsa APIの
結果1,000件あたりの料金
- Sorsa APIの
/search-tweets - $0.07から
- X 直近検索
- $5.00
- X 全アーカイブ検索
- $5.00
- Sorsa APIの
投稿者のプロフィール
- Sorsa APIの
/search-tweets - すべてのツイートに含まれる
- X 直近検索
- 2026年11月22日から1人$0.010で課金
- X 全アーカイブ検索
- 2026年11月22日から1人$0.010で課金
- Sorsa APIの
クエリ構文
- Sorsa APIの
/search-tweets - x.comのウェブ検索
- X 直近検索
- v2演算子、512文字
- X 全アーカイブ検索
- v2演算子、1,024文字
- Sorsa APIの
セットアップ
- Sorsa APIの
/search-tweets - APIキー1つ
- X 直近検索
- 開発者アカウント、App、Bearerトークン
- X 全アーカイブ検索
- 開発者アカウント、App、Bearerトークン
- Sorsa APIの
公式のエンドポイントは、デフォルトでは id と text しか返しません。日付、カウント、投稿者が返るのは、tweet.fields、expansions、user.fields で指定したときだけです。Sorsa APIでは、どのツイートもすべてのフィールドつきで届きます。
#ウェブ構文と公式X APIの演算子の違い
公式X APIは独自の演算子名を使うため、x.comの検索ボックスからコピーしたクエリが、そこでは失敗することがあります。min_faves: と min_retweets: は400エラーで拒否され、日付はクエリではなく start_time と end_time のパラメーターで渡します。Sorsa APIはウェブ構文を受け付けるので、左の列は書いたとおりに動きます。
| やりたいこと | ウェブ構文(x.com、Sorsa API) | 公式X API v2 |
|---|---|---|
| いいね20以上 | min_faves:20 | min_likes:20 |
| リポスト5以上 | min_retweets:5 | min_reposts:5 |
| 2026年10月のみ | since:2026-10-01 until:2026-11-01 | start_time と end_time のパラメーター |
| リプライのみ | filter:replies | is:reply |
| メディアやリンクつきの投稿 | filter:media、filter:links | has:media、has:links |
| リツイート | デフォルトで除外 | 2026年5月4日からキーワード検索で除外 |
| 語句、アカウント、言語 | from:、to:、#、@、"phrase"、lang: | 同じ |
いいね20以上
- ウェブ構文(x.com、Sorsa API)
min_faves:20- 公式X API v2
min_likes:20
リポスト5以上
- ウェブ構文(x.com、Sorsa API)
min_retweets:5- 公式X API v2
min_reposts:5
2026年10月のみ
- ウェブ構文(x.com、Sorsa API)
since:2026-10-01 until:2026-11-01- 公式X API v2
start_timeとend_timeのパラメーター
リプライのみ
- ウェブ構文(x.com、Sorsa API)
filter:replies- 公式X API v2
is:reply
メディアやリンクつきの投稿
- ウェブ構文(x.com、Sorsa API)
filter:media、filter:links- 公式X API v2
has:media、has:links
リツイート
- ウェブ構文(x.com、Sorsa API)
- デフォルトで除外
- 公式X API v2
- 2026年5月4日からキーワード検索で除外
語句、アカウント、言語
- ウェブ構文(x.com、Sorsa API)
from:、to:、#、@、"phrase"、lang:- 公式X API v2
- 同じ
2026年の2つの変更が、古いガイドの内容が食い違う理由です。Xは2026年1月19日に min_likes:、min_replies:、min_reposts: を停止し、5月4日に復活させました。このとき検索が新しいインデックスに移り、キーワードの結果からリツイートも除外されました(Xの変更履歴(新しいタブで開きます))。公式X APIはエンゲージメントのフィルターを無視する、と書いているページやAIの回答は、その間の数か月を説明しているものです。
統合ごと公式エンドポイントから移行するなら、公式X APIからの移行のガイドが、v2のすべてのパラメーターと演算子をSorsa APIに対応づけています。
#今日からツイート検索を始める
コードからのツイート検索は、クエリ1つとカーソル1つに集約されます。Sorsa APIなら、x.comで普段入力しているクエリを POST /search-tweets に送るだけで、2006年までの任意の日付から、投稿者つきで1リクエストあたり約20ツイートが返ります。結果は1,000件あたり$0.07からで、公式X APIの$5.00を大きく下回ります。100回分の無料リクエストで、最初の2,000件を取得できます。
#よくある質問
無料のTwitter検索APIはありますか?
Xにはありません。公式X APIに無料枠はなく、検索が返した投稿1件ごとに$0.005、つまり1,000件あたり$5.00を課金します。Sorsa APIは、新規アカウントすべてに100回分の無料リクエストを付与します。POST /search-tweets で約2,000件の検索結果を取得するのに十分で、カードは不要、有効期限もありません。数回の検索を手作業で試すだけなら、無料のTwitter高度な検索ツールが最初の20件の一致投稿を表示します。
APIでは、どこまで過去のツイートを検索できますか?
最初の公開ツイートが投稿された2006年3月21日までです。公式X APIの直近検索は過去7日間しかカバーせず、全アーカイブ検索が2006年まで届くのは、従量課金とEnterpriseのアクセスです。Sorsa APIの POST /search-tweets は、クエリ内の since: と until: で、2006年までの任意の期間を指定できます。削除されたツイートや非公開アカウントは、どのAPIでも手が届きません。大規模なバックフィルについては、過去のTwitterデータのガイドで解説しています。
ツイートの検索には、どのTwitter APIを使えばよいですか?
ツイートの検索には、Sorsa APIを使ってください。POST /search-tweets は結果1,000件あたり$0.07からで、公式X APIの$5.00を下回り、2006年までさかのぼれます。x.comの検索ボックスの構文をそのまま受け付け、どのツイートにも投稿者のプロフィール全体を含めて返します。APIキー1つで開発者アカウントとOAuthの代わりになり、全プラン毎秒20リクエストです。
ツイートをリアルタイムで検索できますか?
はい、ポーリングで可能です。Latestの検索をスケジュールで実行し、手元にある最新のツイートIDを since_id: に指定すれば、各回に返るのは、その後に投稿されたものだけです。Sorsa APIでは、何も見つからなかった確認は、間隔にかかわらず1リクエストです。Sorsa APIも公式X APIの検索も、ツイートをストリームとして送ってくることはありません。
検索結果にリツイートが出てこないのはなぜですか?
ネイティブのリツイートは他人の投稿のコピーで、X検索はデフォルトでコピーを除外します。Sorsa APIでは、クエリに include:nativeretweets を加えると表示され、filter:nativeretweets を使うとリツイートだけが返ります。公式X APIは、2026年5月4日からキーワード検索でリツイートを返さなくなりました。引用ツイートは自分の本文を持つため、結果に残ります。
#検証の方法
2026年11月2日に、Xの検索ドキュメント(概要、クエリの組み立て、演算子の一覧、レート制限、直近検索のリファレンス)を読みました。Xの料金表、変更履歴、10月23日付のエクスパンション課金のお知らせも確認しています。このページのSorsa APIのリクエストはすべて、/search-tweets、/mentions、/search-users、/user-tweets、/list-tweets の公開中のAPIリファレンスをもとに書きました。レスポンスは架空のアカウントを使った例です。結果1,000件あたりの料金は、料金ページのリクエスト単価から計算しています。
出典
- Search Posts, X API documentation(新しいタブで開きます)
- Search operators, X API documentation(新しいタブで開きます)
- Rate limits, X API documentation(新しいタブで開きます)
- X API pay-per-usage pricing(新しいタブで開きます)
- X API changelog: search endpoints moved to a new index, May 4, 2026(新しいタブで開きます)
- X API PPU expansions update, October 23, 2026(新しいタブで開きます)
- Search Tweets, Sorsa API reference(新しいタブで開きます)
- Search operators, Sorsa API docs(新しいタブで開きます)