Tweet JSON Example: A Real X Post, Field by Field (2026)
A real tweet JSON example from X, explained field by field and mapped to X API v2 and v1.1 names, with reposts, quotes, media and a tested parse script.
Tarun Khatri
Published · Updated · 7 min read
Here is a real tweet JSON example: a NASA post we fetched on 22 October 2026, with every field explained.
It's for developers who parse X (Twitter) posts from an API, an old export or a scraper. You also get each field's name in X API v2 and v1.1, plus reposts, quotes and media. We run Weir, the API that returned it.
Fetch the same post yourself:
curl --request GET \
--url https://api.weirapp.io/v1/x/posts/2041557036274475228 \
--header "Authorization: Bearer $WEIR_API_KEY"
The tweet JSON example, in full
Weir returned this for NASA's "Hello, Moon" post, under data. We cut three of the four photos, two empty lists and the profile picture:
{
"id": "2041557036274475228",
"text": "Hello, Moon. It’s great to be back.\n \nHere’s a taste of what the Artemis II astronauts photographed during their flight around the Moon. Check out more photos from the mission: https://t.co/rzM1P0QbOl https://t.co/6jWINHkDLh",
"url": "https://x.com/NASA/status/2041557036274475228",
"lang": "en",
"createdAt": "2026-04-07T16:41:42.000Z",
"conversationId": "2041557036274475228",
"inReplyToId": null,
"author": { "id": "11348282", "username": "NASA", "followersCount": 92311207 },
"likeCount": 794766,
"retweetCount": 169435,
"replyCount": 9746,
"quoteCount": 9052,
"bookmarkCount": 59698,
"viewCount": 30495055,
"media": [{ "type": "photo", "url": "https://pbs.twimg.com/media/HFURRWmXYAEcq7c.jpg" }],
"entities": { "urls": ["https://www.nasa.gov/artemis-ii-multimedia/"] },
"quotedPost": null,
"retweetedPost": null
}
The call cost 2 credits: 1 for the call and 1 for the post. Five of its counts, as they stood that day:
Views, at 30,495,055, would flatten every other bar.
What each field in the tweet object means
Every field has one job:
idis the post's number, sent as a string.urlis its link on x.com.textis the whole post. Its lastt.colink opens the photos, soentities.urlslists only the NASA page.langis the language X detected, as a tag likeen.createdAtis the posting time in UTC, in ISO 8601.conversationIdnames the thread.inReplyToIdis null because this post isn't a reply.authoris an object:id,username,name, averifiedflag andfollowersCount.- The six counts are likes, reposts, replies, quotes, bookmarks and views.
medialists photos, videos and GIFs in order. A video'surlis its best MP4.entitiesholds hashtags and mentions without#or@, and links already expanded.article,quotedPostandretweetedPoststay null unless the post is an X Article, a quote or a repost.
The id also carries the posting time. Our Tweet ID to date tool reads it out.
Why tweet ids are strings in JSON
X's post ids are bigger than 2^53, the largest whole number a JavaScript number holds exactly. X's archived v1.1 docs warn that some languages "may have difficulty/silent defects" with them.
Here is what happens to NASA's id when it arrives as a number:
JSON.parse('{"id": 2041557036274475228}').id; // 2041557036274475300
JSON.parse('{"id": "2041557036274475228"}').id; // "2041557036274475228"
That's why v1.1 sent both id and id_str. Use id_str there. Weir and v2 send only strings.
Twitter API JSON response: v2 and v1.1 names
The same post comes back with different names in each API. These are the fields most code reads:
| Weir | X API v2 | v1.1 |
|---|---|---|
id |
id |
id_str |
text |
text |
full_text or text |
createdAt |
created_at |
created_at |
author.username |
username in includes.users |
user.screen_name |
likeCount |
public_metrics.like_count |
favorite_count |
retweetCount |
public_metrics.retweet_count |
retweet_count |
replyCount |
public_metrics.reply_count |
reply_count |
bookmarkCount |
public_metrics.bookmark_count |
none |
The formats differ too. v1.1 wrote created_at as "Wed Oct 10 20:19:24 +0000 2018", while v2 and Weir use ISO 8601.
In v2 you ask for most fields. A bare request returns only id, text and edit_history_tweet_ids. Add tweet.fields=created_at,public_metrics and expansions=author_id for the rest.
In v1.1, reply_count and quote_count came only with the Premium and Enterprise tiers, says X's archived data dictionary. Weir's viewCount has no exact twin: v2's impression_count counts times a post "appeared on a user's screen."
How reposts, quotes and media look in tweet JSON
Each API nests the related post its own way:
| Weir | X API v2 | v1.1 |
|---|---|---|
retweetedPost |
referenced_tweets, type retweeted |
retweeted_status |
quotedPost |
referenced_tweets, type quoted |
quoted_status |
inReplyToId |
referenced_tweets, type replied_to |
in_reply_to_status_id_str |
media[].url |
includes.media[].url |
extended_entities.media |
entities.mentions |
entities.mentions[].username |
entities.user_mentions |
entities.hashtags |
entities.hashtags[].tag |
entities.hashtags[].text |
In v2, the referenced post itself arrives in includes.tweets when you add expansions=referenced_tweets.id.
We saw Weir's repost wrapper in a real search of @XDevelopers on 22 October 2026. One repost, trimmed:
{
"id": "2113062427566969325",
"text": "RT @...: New to the X MCP ...",
"likeCount": 0,
"retweetCount": 14,
"retweetedPost": { "id": "2113060281354240105", "likeCount": 133, "retweetCount": 14 }
}
- The wrapper's own
likeCountis 0. The original had 133 likes, so read counts fromretweetedPost. - Its
textis cut short and starts with "RT @". The full text is inretweetedPost.text, as v1.1 kept it inretweeted_status. - A quote is the other way round. In the same search, an @XDevelopers quote had 120 likes of its own, and its
quotedPosthad 128.
That quoted post was an X Article, so it carried an article object too. Our guide to reading X Articles via API covers that shape.
Media differs most. v1.1 listed every video bitrate in video_info.variants, and v2 does the same in variants. Weir picks the highest-bitrate MP4 and gives it as url, with the poster frame in previewImageUrl.
Parse a tweet JSON in Python
This script reads a saved response and handles each trap above. Save the curl output as post.json, then run it:
import json
def summarize(post):
original = post["retweetedPost"] or post # a repost wraps the real post
return {
"id": post["id"], # a string: never int() or float() it
"repost": post["retweetedPost"] is not None,
"likes": original["likeCount"], # None means X didn't report it
"quotes": (post["quotedPost"] or {}).get("id"),
"photos": sum(1 for m in original["media"] if m["type"] == "photo"),
"links": original["entities"]["urls"],
}
with open("post.json", encoding="utf-8") as f:
print(summarize(json.load(f)["data"]))
On our saved NASA response it prints:
{'id': '2041557036274475228', 'repost': False, 'likes': 794766, 'quotes': None, 'photos': 4, 'links': ['https://www.nasa.gov/artemis-ii-multimedia/']}
Run on the three @XDevelopers results, it flagged both reposts, with 133 and 81 likes, and the quote's target id. To pull many posts at once, see how to get tweets with Python.
When not to use Weir
- You need X's exact v2 shape. Weir uses its own camelCase names, so v2 code needs the table above.
- You need to post or reply. Weir is read-only.
- A contract with X is required. Weir reads public data and isn't licensed by X, so access can change.
- You only parse old v1.1 files. You need no API at all, just the name tables.
FAQ
What does a tweet look like in JSON?
An X API post in JSON is one object with the post's id, text, time, author and counts. Media, links and mentions sit in lists, and reposts or quotes nest a second post inside. The example at the top shows every field Weir returns.
What is the difference between id and id_str in tweet JSON?
They hold the same number. In v1.1, id was a number, which JavaScript and other languages can round, and id_str was the same id as a string. v2 and Weir send only the string form.
How do I tell if a tweet is a retweet in the JSON?
Look for the original post nested inside. Weir sets retweetedPost, v1.1 sets retweeted_status, and v2 lists a referenced_tweets entry of type retweeted. A repost's own like count is 0 on Weir, so read the original's.
Where is the full text of a tweet in the API response?
In v2 and on Weir, text holds the full post. v1.1 could send a shortened text with truncated set to true, and the whole post came in full_text. For posts over 280 characters, v2 also adds note_tweet.
Sources
All checked on 22 October 2026:
- X API v2 data dictionary: https://docs.x.com/x-api/fundamentals/data-dictionary
- X API metrics: https://docs.x.com/x-api/fundamentals/metrics
- X API Get Posts by ID reference: https://docs.x.com/x-api/posts/get-post-by-id
- X API changelog (3 June 2026 entry): https://docs.x.com/changelog
- X v1.1 Tweet object, archived 4 January 2025: https://web.archive.org/web/20250104163403/https://developer.x.com/en/docs/x-api/v1/data-dictionary/object-model/tweet
- X v1.1 entities object, archived 1 December 2024: https://web.archive.org/web/20241201134222/https://developer.x.com/en/docs/x-api/v1/data-dictionary/object-model/entities
- X v1.1 extended entities, archived 10 December 2024: https://web.archive.org/web/20241210205929/https://developer.x.com/en/docs/x-api/v1/data-dictionary/object-model/extended-entities
- X v1.1 to v2 data format mapping, archived 12 December 2024: https://web.archive.org/web/20241212045531/https://developer.x.com/en/docs/x-api/migrate/data-formats/standard-v1-1-to-v2
- Weir response shapes: https://docs.weirapp.io/response-shapes
- Our get_x_post call for NASA's post and search_x call for @XDevelopers through Weir, 22 October 2026