# Response format

> TwittrAPI returns X's raw GraphQL JSON unchanged. The exceptions (search, lookups, account actions) and how to read timelines, tweets and users.

HTML page: https://www.twittrapi.com/docs/response-format

Most endpoints return exactly the JSON that X's web app receives for the same request: X's internal GraphQL API, passed through without changes. That gives you every field X sends, but the shape is X's, not ours, and X changes it from time to time.

Each reference page names the X query behind the endpoint (for example `UserByScreenName` or `UserTweets`) and says where the data is.

## Reading X's JSON

**Single objects.** A user lookup returns `data.user.result`, with the numeric ID in `rest_id`. A single tweet returns `data.tweetResult.result`.

**Timelines** (user tweets, followers, lists, communities, search) return a list of `instructions`. Content is in the `TimelineAddEntries` instruction:

```json
{
  "type": "TimelineAddEntries",
  "entries": [
    {
      "entryId": "tweet-1790000000000000000",
      "content": {
        "entryType": "TimelineTimelineItem",
        "itemContent": {
          "itemType": "TimelineTweet",
          "tweet_results": { "result": { "rest_id": "1790000000000000000", "...": "..." } }
        }
      }
    },
    { "entryId": "cursor-bottom-...", "content": { "cursorType": "Bottom", "value": "..." } }
  ]
}
```

- `entryId` prefixes tell you what an entry is: `tweet-`, `user-`, `profile-conversation-` and `conversationthread-` (threads), `cursor-top-` and `cursor-bottom-`.
- Users come as `user_results.result`, tweets as `tweet_results.result`. A tweet's author is nested inside the tweet.
- Some results are wrapped in a `TweetWithVisibilityResults` object with the tweet under `tweet`.
- A pinned tweet comes in a separate `TimelinePinEntry` instruction.

Write parsers that search for these markers instead of following one fixed path, and treat every field as optional. The [examples repository](https://github.com/twittrapi/examples) has small extractors for Python, Node.js, Go and jq.

## Exceptions

These endpoints return something other than X's raw GraphQL response:

| Endpoint | Response |
| --- | --- |
| `GET /search` | `{"category": "Latest", "entries": [...]}`: the tab you searched and X's instructions array. |
| `GET /username/to/id/{username}` | `{"userId": "12"}` |
| `GET /user/usernames/to/ids` | `{"userIds": {"jack": "12"}}` (unresolved handles are left out) |
| `GET /user/usernames/status` | `{"usernamesStatus": {"jack": "active"}}` |
| `GET /user/by/username/{username}` | X's JSON, or `{"data": {}, "userExists": false}` when the handle does not exist |
| `GET /trends/{locationId}`, `GET /misc/locations`, `GET /user/friendships/show`, `GET /misc/emojis` | X's older v1.1 JSON (not GraphQL) |
| Account actions (`/client/*`) | `{"status_code": 200, "response": "<X body as a string>"}`. Parse `response` again to get X's JSON. |
| Direct messages (`/client/dm/*`) | JSON built by the API (conversations, decrypted messages, settings) with X's field names; see each [endpoint page](https://www.twittrapi.com/docs/account-actions#direct-messages). |

## Errors

Errors are always `{"error": "..."}` with a non-2xx status. See [Errors](https://www.twittrapi.com/docs/helpful-infos/error-handling).

## Example responses

Reference pages show a captured example response where one is available. Until then they show a placeholder. The SDKs return the same JSON, unmodified.

## Coming from another API

If your code expects flat objects or the v2 `data` / `includes` shape, the migration guides map those fields to X's JSON and include adapters: [from twitterapi.io](https://www.twittrapi.com/guides/migrate-from-twitterapi-io), [from SocialData](https://www.twittrapi.com/guides/migrate-from-socialdata) and [from the official X API](https://www.twittrapi.com/guides/migrate-from-official-x-api).
