Search tweets
Search tweets or people with the same query syntax as the X search box.
/searchFree tool: Tweet ID to date, Shadowban checker, no API key needed.
This is the Search tab of X. The query supports X search operators, and the optional filters object adds operators for you. Results come one page at a time.
The same endpoint also answers on:
POST /search(same handler; the request body is ignored, parameters go in the query string)GET /search/{searchItem}(query as a URL-encoded path segment instead of ?searchItem)POST /search/{searchItem}GET /search_v2(same, but skips the control-character check)POST /search_v2
Use the path above in new code; the aliases are kept for existing clients.
Parameters
searchItemquery · string · requiredSearch query, e.g. from:jack lang:en. Required unless filters is set. query is accepted as an alias. When the query contains operators, + is read as a space. Query plus filters may be at most 512 characters.
categoryquery · string · optional · default TopSearch tab: Top, Latest, People, Photos or Videos. Any other value is treated as Top.
countquery · integer · optional · default 20Number of results to ask X for. Sent to X as is; X treats it as a hint and decides how many it returns (follower and following pages often hold 50 to 70 users for count=20). A value that is not a number falls back to 20.
cursorquery · string · optionalBottom cursor from the previous page. Leave it out for the first page. See Pagination.
filtersquery · JSON object (URL-encoded) · optionalExtra conditions as JSON, e.g. {"lang":"en","minimumLikesCount":100}. Each key becomes an operator that is appended to the query. Keys are listed below.
Paginated: pass the bottom cursor of one page as cursor to get the next. Each page is one billed call. See Pagination.
Filter keys
Keys of the filters JSON object and the operator each one adds to the query. Values with the wrong type are ignored; values with the wrong format return 422.
| Key | Type | Adds |
|---|---|---|
| lang | string | lang:<code> (must be a language code X knows, e.g. en, de, ja, und) |
| since / until | string | since:/until: (YYYY-MM-DD or YYYY-MM-DD_HH:MM:SS_UTC) |
| sinceTime / untilTime | string of digits | since_time:/until_time: (Unix seconds) |
| withinTime | string | within_time: (e.g. 2d, 3h, 5m, 30s) |
| sinceId / maxId | string of digits | since_id:/max_id: |
| exactSentence | string | "exact phrase" |
| anyOfTheseWords | string[] | (a OR b OR c) |
| noneOfTheseWords | string[] | -a -b |
| hashtags | string[] | (#a OR #b) |
| fromTheseAccounts / toTheseAccounts / mentionsTheseAccounts | string[] | (from:a OR from:b), (to:…), (@a OR @b) |
| minimumRepliesCount / minimumRetweetsCount / minimumLikesCount | number | min_replies:/min_retweets:/min_faves: |
| maximumRepliesCount / maximumRetweetsCount / maximumLikesCount | number | -min_replies:/-min_retweets:/-min_faves: |
| removeReplies / onlyReplies | boolean | -filter:replies / filter:replies |
| removePostsWithLinks / onlyPostsWithLinks | boolean | -filter:links / filter:links |
| removePostsWithMedia / onlyPostsWithMedia | boolean | -filter:media / filter:media |
| removePostsWithVideo / onlyPostsWithVideo | boolean | -filter:native_video / filter:native_video |
| removePostsWithPhotos / onlyPostsWithPhotos | boolean | -filter:images / filter:images |
| linksInclude | string | url:<text> |
| includeRetweets | boolean | include:nativeretweets |
| onlyRetweets | boolean | filter:nativeretweets |
| onlyOldStyleRetweets / removeOldStyleRetweets | boolean | filter:retweets / -filter:retweets |
| onlyQuotes / onlySelfThreads | boolean | filter:quote / filter:self_threads |
| onlyVerified / onlyBlueVerified | boolean | filter:verified / filter:blue_verified |
| listId | string | list:<id> |
| conversationId / quotedTweetId / quotedUserId | string of digits | conversation_id:/quoted_tweet_id:/quoted_user_id: |
| hasEngagement | boolean | filter:has_engagement |
| onlyAllVideos / onlySpaces / onlyGifs | boolean | filter:videos / filter:spaces / card_name:animated_gif |
| onlyWithMentions / onlyWithHashtags / onlyNews / safeMode | boolean | filter:mentions / filter:hashtags / filter:news / filter:safe |
| near / within / geocode / place | string | near:, within: (10km, 5mi), geocode: (lat,long,radius), place: |
| source / cardName / cardDomain | string | source:, card_name:, card_domain: |
Operators accepted in the query text: from:, to:, filter:, include:, lang:, since:, until:, since_time:, until_time:, within_time:, since_id:, max_id:, min_replies:, min_retweets:, min_faves:, list:, url:, near:, within:, geocode:, source:, card_name:, card_domain:, card_url:, place:, place_country:, point_radius:, bounding_box:, entity:, conversation_id:, quoted_tweet_id:, quoted_user_id:, quotes_of_tweet_id:, context:, has:, is:. Any other word: outside double quotes returns 422.
Notes
- An empty timeline from X is retried with other accounts, up to 9 upstream calls. You are billed once.
- Mutually exclusive filter pairs (for example removeReplies and onlyReplies) return 422 when both are true.
Example request
curl 'https://api.twittrapi.com/search?searchItem=from%3Ajack%20lang%3Aen&category=Latest&count=20' \
--header 'X-API-KEY: YOUR_API_KEY'from twittrapi import TwittrAPI
client = TwittrAPI(api_key="YOUR_API_KEY")
data = client.search.tweets("from:jack lang:en", category="Latest", count=20)import { TwittrAPI } from "twittrapi";
const client = new TwittrAPI({ apiKey: process.env.TWITTRAPI_API_KEY });
const data = await client.search.tweets({ query: "from:jack lang:en", category: "Latest", count: 20 });curl 'https://twitter-aio.p.rapidapi.com/search?searchItem=from%3Ajack%20lang%3Aen&category=Latest&count=20' \
--header 'x-rapidapi-key: YOUR_RAPIDAPI_KEY' \
--header 'x-rapidapi-host: twitter-aio.p.rapidapi.com'Base URL https://api.twittrapi.com, key in the X-API-KEY header. Python and Node.js use the official SDKs.
Response
Not the raw GraphQL object: {"category": "<tab>", "entries": [...]}, where entries is the instructions array of X's SearchTimeline (data.search_by_raw_query.search_timeline.timeline.instructions). Tweets and users are inside TimelineAddEntries; the bottom cursor is an entry with cursorType "Bottom".
Simple format (?format=simple or X-Response-Format: simple): Collection of Tweet objects: {data: [Tweet], nextCursor, previousCursor, hasNextPage}. With category=People: User objects. Schema.
{
"category": "Latest",
"entries": [
{
"entries": [
{
"content": {
"__typename": "TimelineTimelineItem",
"clientEventInfo": {
"component": "latest_nightowl_recency",
"details": {
"timelinesDetails": {
"controllerData": "DAACDAAFDAABDAABDAABCgABAAAAAEAAAAAAAAwAAgoAAQAAAAAAAAABCgACAs0NDBLG4QoLAAMAAAAGb3BlbmFpCgAFPRJJmRFfu2sIAAYAAAABCgAH+7BbkIqSCzgKAAgAAAGhJ3PRlgAAAAAA"
}
},
"element": "tweet"
},
"entryType": "TimelineTimelineItem",
"itemContent": {
"__typename": "TimelineTweet",
"highlights": {
"textHighlights": [
{
"endIndex": 159,
"startIndex": 153
}
]
},
"itemType": "TimelineTweet",
"tweetDisplayType": "Tweet",
"tweet_results": {
"result": {
"__typename": "Tweet",
"cashtag_attachments": [],
"core": {
"user_results": {
"result": {
"__typename": "User",
"action_counts": {
"favorites_count": 2972
},
"affiliates_highlighted_label": {},
"avatar": {
"image_url": "https://pbs.twimg.com/profile_images/1000000000000000000/example_normal.jpg"
},
"banner": {
"image_url": "https://pbs.twimg.com/profile_banners/1000000000000000000/1700000000"
},
"core": {
"created_at": "Mon Aug 24 10:29:06 +0000 2026",
"name": "Example User 1",
"screen_name": "example_user_1"
},
"dm_permissions": {
"can_dm": false
},
"follow_request_sent": false,
"grok_translated_bio_with_availability": {
"is_available": false
},
"has_graduated_access": true,
"id": "VXNlcjoxMDAwMDAwMDAwMDAwMDAwMDAx",
"is_blue_verified": false,
"location": {
"location": "Example"
},
"media_permissions": {
"can_media_tag": true
},
"notifications_settings": {
"notifications_enabled": false
},
"parody_commentary_fan_label": "None",
"pinned_items": {},
"possibly_sensitive": false,
"privacy": {
"protected": false
},
"profile_bio": {
"description": "Example",
"entities": {
"description": {}
}
},
"profile_image_shape": "Circle",
"profile_metadata": {
"profile_interstitial_type": ""
},
"profile_translation": {
"translator_type": "none"
},
"relationship_counts": {
"followers": 1290,
"following": 1091
},
"relationship_perspectives": {
"blocked_by": false,
"blocking": false,
"followed_by": false,
"following": false,
"live_following": false,
"muting": false
},
"rest_id": "1000000000000000001",
"super_follow_eligible": false,
"super_followed_by": false,
"super_following": false,
"tweet_counts": {
"media_tweets": 119,
"tweets": 2136
},
"verification": {
"verified": false
},
"website": {
"url": ""
}
}
}
},
"edit_control": {
"edit_tweet_ids": [
"2000000000000000001"
],
"editable_until_msecs": "1791666816000",
"edits_remaining": "5",
"is_edit_eligible": false
},
"grok_analysis_button": true,
"grok_annotations": {},
"grok_translated_post_with_availability": {
"is_available": false
},
"is_translatable": false,
"legacy": {
"bookmark_count": 0,
"bookmarked": false,
"conversation_id_str": "2109008936460275850",
"created_at": "Sat Oct 10 20:13:36 +0000 2026",
"display_text_range": [
12,
274
],
"entities": {
"user_mentions": [
{
"id_str": "1000000000000000002",
"indices": [
0,
11
],
"name": "Example User 2",
"screen_name": "example_user_2"
}
]
},
"favorite_count": 0,
"favorited": false,
"full_text": "Example text.",
"id_str": "2000000000000000001",
"in_reply_to_screen_name": "example_user_2",
"in_reply_to_status_id_str": "2000000000000000002",
"in_reply_to_user_id_str": "1000000000000000002",
"is_quote_status": false,
"lang": "en",
"quote_count": 0,
"reply_count": 0,
"retweet_count": 0,
"retweeted": false,
"user_id_str": "1000000000000000001"
},
"rest_id": "2000000000000000001",
"unmention_data": {},
"views": {
"count": "2",
"state": "EnabledWithCount"
}
}
}
}
},
"entryId": "tweet-2000000000000000001",
"sortIndex": "2109014707363905533"
},
{
"content": {
"__typename": "TimelineTimelineCursor",
"cursorType": "Top",
"entryType": "TimelineTimelineCursor",
"value": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAABCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3ZngxRXVTaEMydkVmSFVTNWRTeVhJWU1kUkxsSjVSZUFGUjFFdVc1eFc5R1hIVVM1UjQ4YXdLMGRSTGxoV05kZzJSMUV1YTBSbDlHSEhVUzVkVTFia1MwZFJMazJvSmRSb1IxRXVVRURXc0FPSFVTNWZoQWFvU3NkUkxsbVJwYlF0aDFFdVpRdVdrR2xIVVM1cWI1YkVHTWRSTG1GTmxjUXFCMUV1VlhtMXZHcgAA"
},
"entryId": "cursor-top-9223372036854775807",
"sortIndex": "9223372036854775807"
},
{
"content": {
"__typename": "TimelineTimelineCursor",
"cursorType": "Bottom",
"entryType": "TimelineTimelineCursor",
"value": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAACCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3ZngxRXVTaEMydkVmSFVTNWRTeVhJWU1kUkxsSjVSZUFGUjFFdVc1eFc5R1hIVVM1UjQ4YXdLMGRSTGxoV05kZzJSMUV1YTBSbDlHSEhVUzVkVTFia1MwZFJMazJvSmRSb1IxRXVVRURXc0FPSFVTNWZoQWFvU3NkUkxsbVJwYlF0aDFFdVpRdVdrR2xIVVM1cWI1YkVHTWRSTG1GTmxjUXFCMUV1VlhtMXZHcgAA"
},
"entryId": "cursor-bottom-0",
"sortIndex": "0"
}
],
"type": "TimelineAddEntries"
}
]
}{
"data": [
{
"id": "2000000000000000001",
"url": "https://x.com/example_user_1/status/2000000000000000001",
"text": "Example text.",
"createdAt": "2026-10-10T20:13:36Z",
"lang": "en",
"author": {
"id": "1000000000000000001",
"username": "example_user_1",
"name": "Example User 1",
"description": "Example",
"location": "Example",
"url": null,
"createdAt": "2026-08-24T10:29:06Z",
"avatarUrl": "https://pbs.twimg.com/profile_images/1000000000000000000/example.jpg",
"bannerUrl": "https://pbs.twimg.com/profile_banners/1000000000000000000/1700000000",
"verified": false,
"verifiedType": null,
"protected": false,
"counts": {
"followers": 1290,
"following": 1091,
"tweets": 2136,
"likes": 2972,
"media": 119,
"listed": 0
},
"pinnedTweetIds": [],
"isAutomated": false
},
"counts": {
"likes": 0,
"retweets": 0,
"replies": 0,
"quotes": 0,
"bookmarks": 0,
"views": 2
},
"media": [],
"urls": [],
"hashtags": [],
"mentions": [
{
"id": "1000000000000000002",
"username": "example_user_2"
}
],
"replyTo": {
"tweetId": "2000000000000000002",
"userId": "1000000000000000002",
"username": "example_user_2"
},
"quoted": null,
"retweetOf": null,
"conversationId": "2109008936460275850",
"isPinned": false,
"source": null,
"article": null
}
],
"nextCursor": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAACCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3ZngxRXVTaEMydkVmSFVTNWRTeVhJWU1kUkxsSjVSZUFGUjFFdVc1eFc5R1hIVVM1UjQ4YXdLMGRSTGxoV05kZzJSMUV1YTBSbDlHSEhVUzVkVTFia1MwZFJMazJvSmRSb1IxRXVVRURXc0FPSFVTNWZoQWFvU3NkUkxsbVJwYlF0aDFFdVpRdVdrR2xIVVM1cWI1YkVHTWRSTG1GTmxjUXFCMUV1VlhtMXZHcgAA",
"previousCursor": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAABCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3ZngxRXVTaEMydkVmSFVTNWRTeVhJWU1kUkxsSjVSZUFGUjFFdVc1eFc5R1hIVVM1UjQ4YXdLMGRSTGxoV05kZzJSMUV1YTBSbDlHSEhVUzVkVTFia1MwZFJMazJvSmRSb1IxRXVVRURXc0FPSFVTNWZoQWFvU3NkUkxsbVJwYlF0aDFFdVpRdVdrR2xIVVM1cWI1YkVHTWRSTG1GTmxjUXFCMUV1VlhtMXZHcgAA",
"hasNextPage": true
}In the raw format, field names and nesting come from X and can change without notice. See Response format; the simple format keeps a fixed schema.
Errors
- 400Query and filters are both empty, or filters is not valid JSON.
- 422The query has control characters (not checked on /search_v2), is longer than 512 characters, contains [ or ], has an unclosed double quote or unbalanced parentheses, uses an unsupported operator, or a filters value has the wrong format. X validation errors also return 422.
- 502X returned an empty timeline 9 times in a row. Body: {"error": "...", "attempts": 9}. Refunded.
Errors every endpoint can return (401, 402, 403, 404, 408, 409, 429, 5xx), and which of them are charged, are on the Errors page. Calls that fail with 400, 408, 409 or a 5xx error are refunded.