Twitter / X Search Scraper API
Our Twitter search scraper takes a keyword, hashtag, or query and a search tab, then returns the tweets X embeds for that query as structured JSON: text, author, language, and engagement per result. This endpoint is in beta because X aggressively walls logged-out search, so we return what is available and report clearly when a query comes back empty.
Why Twitter / X Search data sits behind a login wall
X search is one of the hardest surfaces on the public web to read: a logged-out request to the search page returns a JavaScript shell with a login gate and, most of the time, no tweet data embedded at all. The official API can search, but only behind a paid developer plan that starts around 100 dollars a month.
One request to the Twitter / X Search Scraper API
curl "https://api.twitterscraperapi.com/api/v1/xtwitter/search?q=nasa&f=top&api_key=$API_KEY" import requests, os
BASE = "https://api.twitterscraperapi.com"
API_KEY = os.environ["API_KEY"]
# Query plus a search tab: top | live | user | image | video.
resp = requests.get(
f"{BASE}/api/v1/xtwitter/search",
params={
"q": "nasa",
"f": "top",
"limit": 20,
"api_key": API_KEY,
},
timeout=30,
)
data = resp.json()
# X walls logged-out search hard, so always check results_count first.
print(data["query"], "->", data["results_count"], "tweets")
for t in data["results"]:
print(t["position"], t["author"], "-", t["full_text"]) Parameters
| Parameter | Required | Default | Notes |
|---|---|---|---|
q | required | - | The search query X accepts on /search. A keyword, phrase, @handle, or #hashtag, e.g. nasa or #space. |
f | optional | top | Search tab: top, live, user, image, or video. Maps to X's own f parameter. Defaults to top. |
limit | optional | - | Max number of tweets to return, 1 to 250. We slice the parsed list to this size. |
url | optional | - | Alternatively pass a full x.com/search URL and we read the q and f from it instead of the separate params. |
api_key | required | - | Your API key, passed as a query parameter. Get one free at signup. |
The Twitter / X Search Scraper API response, field by field
{
"query": "nasa",
"page": 1,
"results_count": 1,
"total_results": 1,
"results": [
{
"position": 1,
"id": "20",
"title": "just setting up my twttr",
"url": "https://x.com/jack/status/20",
"price": null,
"currency": "USD",
"rating": null,
"reviews_count": null,
"thumbnail": null,
"author": "jack",
"full_text": "just setting up my twttr",
"lang": "en",
"retweet_count": null,
"favorite_count": 308537,
"reply_count": 17947,
"created_at": "2006-03-21T20:50:14.000Z"
}
]
} | Field | Type | Description |
|---|---|---|
query | string | The query that was searched, echoed back from your q input. |
page | integer | The result page number, currently 1 per request. |
results_count | integer | Number of tweets returned in this response. Check this first, since a walled query can return 0. |
total_results | integer | Total tweets parsed from the page before any limit slice was applied. |
results | array | The matched tweets. Each item carries position, id, title, url, author, full_text, lang, created_at, and engagement counts. |
results[].author | string | The screen_name of the tweet's author. |
results[].full_text | string | The tweet body. title carries the same text for cross-category consistency. |
results[].favorite_count | integer or null | Likes on the tweet when X embeds the figure, otherwise null. |
results[].reply_count | integer or null | Replies on the tweet when present in the embedded data, otherwise null. |
results[].created_at | string or null | When the tweet was posted, when X includes it in the embedded payload. |
Where this Twitter / X Search data goes to work
Keyword and brand monitoring
Hashtag tracking
Topic and trend sampling
Media discovery
Enrich a query list
Feed matches to an LLM
What sets our Twitter / X Search Scraper API apart
Point the endpoint at a query and tab and we fetch X's search page through rotating proxies, parse the tweet objects embedded in its bootstrap state, and return them as validated JSON with no login and no paid X plan. Because X hard-walls logged-out search, we are honest about it: the endpoint is beta, every response carries a results_count so you can tell a real hit from an empty one, and a fully walled query returns a clear diagnostic rather than a fabricated feed.
Query and tab input
No login or paid X plan
Honest, classifiable results
Anti-bot and proxy rotation
Consistent result shape
Pay for success
Twitter / X Search Scraper API or the official X API
| Our API | DIY (requests / headless) | Official X API v2 | |
|---|---|---|---|
| Search by keyword or hashtag | Yes, q plus a search tab | Fetch and dig the page state yourself | Recent and full-archive search, paid tiers |
| Setup | API key only | Proxies, headless browser, parser | Developer account plus paid tier |
| Logged-out access | Best-effort, results_count tells you | Login shell, usually no tweets embedded | Auth token required on every call |
| Cost | Free tier, then per successful request | Free code, but you run the proxies | Plans start around 100 dollars a month |
| Reliability on X search | Beta, X walls this surface hard | Brittle, breaks on every markup change | Stable, but gated and metered |
| Output | Stable flat JSON per tweet | Whatever you parse from the shell | Nested JSON you map yourself |
Start free, pay as you grow
| Plan | Price | Best for |
|---|---|---|
| Free | 1,000 requests | Testing and small jobs |
| Pro | $0.60 / 1k | Production workloads |
| Pay-as-you-go | $0.90 / 1k | Spiky or one-off volume |
Median response 2.6s. You only pay for successful requests.
FAQ
A Twitter search scraper is a tool that runs a keyword, hashtag, or query against X's search and returns the matching tweets in a structured format. Our search endpoint takes a q query and an f tab, fetches X's public search page, parses the tweet objects embedded in its state, and returns them as JSON with text, author, language, and engagement per result.
Because X is one of the most aggressive logged-out walls on the web. A guest request to the search page usually returns a JavaScript shell with a login gate and no tweet data embedded, since results stream in later over X's authenticated API. Our endpoint parses whatever tweets X does embed in the initial page and reports a clear diagnostic when a query comes back empty, so we keep it labelled beta rather than promising a full public search feed.
Check results_count on the response before reading results. It is the number of tweets we parsed for that query. When X serves only a login shell, results_count is 0 and the response includes a diagnostic noting the page length and which markers were present, so you can tell an empty result apart from a genuine no-match.
The f parameter accepts the same tabs X uses on /search: top, live, user, image, and video. It defaults to top. The tab is passed straight through to X, so image and video bias the query toward tweets with media when X embeds them.
No. You authenticate with a single twitterscraperapi key. There is no X developer account and no paid X API tier, which for search starts around 100 dollars a month. The free tier includes 1,000 requests. For a reliable single-tweet read, the tweet endpoint is far more consistent than search because it uses X's public syndication payload.
No tool can guarantee that from logged-out access, and we do not claim to. X only exposes a slice of matching tweets to guests, and often none, so this endpoint returns the tweets embedded in the search page up to your limit rather than a complete historical set. For exhaustive archive search you would need X's paid full-archive API tier.