# Search tweets

`GET https://api.twittrapi.com/search`

Search tweets or people with the same query syntax as the X search box.

HTML page: https://www.twittrapi.com/docs/reference/search

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 main path in new code; the aliases are kept for existing clients.

## Parameters

| Name | In | Type | Required | Default | Description |
| --- | --- | --- | --- | --- | --- |
| `searchItem` | query | string | yes |  | Search 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. |
| `category` | query | string | no | Top | Search tab: Top, Latest, People, Photos or Videos. Any other value is treated as Top. |
| `count` | query | integer | no | 20 | Number 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. |
| `cursor` | query | string | no |  | Bottom cursor from the previous page. Leave it out for the first page. See Pagination. |
| `filters` | query | JSON object (URL-encoded) | no |  | Extra conditions as JSON, e.g. {"lang":"en","minimumLikesCount":100}. Each key becomes an operator that is appended to the query. Keys are listed below. |

Every read endpoint also accepts `format=simple` (or the header `X-Response-Format: simple`) for compact, flat JSON with a fixed schema. Same price.

Paginated: pass the bottom cursor of one page as `cursor` to get the next. Each page is one billed call.

## 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.

## 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".

With `format=simple`: Collection of Tweet objects: {data: [Tweet], nextCursor, previousCursor, hasNextPage}. With category=People: User objects.

## Errors

| Status | When |
| --- | --- |
| 400 | Query and filters are both empty, or filters is not valid JSON. |
| 422 | The 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. |
| 502 | X returned an empty timeline 9 times in a row. Body: {"error": "...", "attempts": 9}. Refunded. |

Shared errors (401 missing key, 402 no balance, 429 rate limit, 5xx) are listed on https://www.twittrapi.com/docs/helpful-infos/error-handling. Calls that fail with 400, 408, 409 or a 5xx error are refunded.

## Example request

curl:

```bash
curl 'https://api.twittrapi.com/search?searchItem=from%3Ajack%20lang%3Aen&category=Latest&count=20' \
  --header 'X-API-KEY: YOUR_API_KEY'
```

Python:

```python
from twittrapi import TwittrAPI

client = TwittrAPI(api_key="YOUR_API_KEY")
data = client.search.tweets("from:jack lang:en", category="Latest", count=20)
```

Node.js:

```js
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 });
```

RapidAPI:

```bash
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'
```

## Example response

Shortened: arrays keep their first items and long strings are cut.

Raw (default):

```json
{
  "category": "Latest",
  "entries": [
    {
      "entries": [
        {
          "content": {
            "__typename": "TimelineTimelineItem",
            "clientEventInfo": {
              "component": "latest_nightowl_recency",
              "details": {
                "timelinesDetails": {
                  "controllerData": "DAACDAAFDAABDAABDAABCgABAAAAAEAAAAAAAAwAAgoAAQAAAAAAAAABCgACAs0NDBLG4QoLAAMAAAAGb3BlbmFpCgAFPRJJmRFfu2sIAAYAAAABCgAH+7Bb…"
                }
              },
              "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": ""
                        },
… (102 more lines)
```

Simple (`format=simple`):

```json
{
  "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": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAACCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3Zngx…",
  "previousCursor": "DAADDAABCgABHUS5rRGX0YcKAAIdRLkhaRohfwAIAAIAAAABCAADAAAAAAgABAAAAAAKAAUdRLmzyoAnEAoABh1EubPKf9jwCwAHAAAA8EVtUEM2d0FBQWZRL2dHSk4wdkdwL0FBQUFCUWRSTGszZmRidzZCMUV1U2M0VnJGWkhVUzVJV2thSVg4ZFJMbHdOTmR3Zngx…",
  "hasNextPage": true
}
```
