Docs
Response format

Response format

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

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:

{
  "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 has small extractors for Python, Node.js, Go and jq.

Exceptions

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

EndpointResponse
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/emojisX'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.

Errors

Errors are always {"error": "..."} with a non-2xx status. See Errors.

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, from SocialData and from the official X API.