Documentation Index
Fetch the complete documentation index at: https://docs.sorsa.io/llms.txt
Use this file to discover all available pages before exploring further.
Tweet Engagement: Comments, Quotes, and Retweets
Every tweet on X generates three types of public engagement: comments (replies), quote tweets, and retweets. The aggregate counts are visible on the tweet itself, but the actual people and content behind those numbers are not - unless you use an API. Sorsa provides dedicated endpoints to extract all three: who replied and what they said, who quoted the tweet and what they added, and who retweeted it.
This guide covers how to retrieve a tweet’s full engagement data, from a high-level metrics snapshot down to the individual replies, quotes, and retweeters.
Before drilling into individual engagement, you often want the overview. The /tweet-info endpoint returns the full tweet object including all engagement counters.
Simplest Example
curl -X POST https://api.sorsa.io/v3/tweet-info \
-H "ApiKey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tweet_link": "https://x.com/elonmusk/status/1234567890"}'
import requests
API_KEY = "YOUR_API_KEY"
def get_tweet(tweet_link):
resp = requests.post(
"https://api.sorsa.io/v3/tweet-info",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json={"tweet_link": tweet_link},
)
resp.raise_for_status()
return resp.json()
tweet = get_tweet("https://x.com/elonmusk/status/1234567890")
print(f"Text: {tweet['full_text'][:100]}...")
print(f"Likes: {tweet.get('likes_count', 0):,}")
print(f"Retweets: {tweet.get('retweet_count', 0):,}")
print(f"Quotes: {tweet.get('quote_count', 0):,}")
print(f"Replies: {tweet.get('reply_count', 0):,}")
print(f"Views: {tweet.get('view_count', 0):,}")
print(f"Bookmarks:{tweet.get('bookmark_count', 0):,}")
For multiple tweets at once, use /tweet-info-bulk with up to 100 tweet links per request (see Optimizing API Usage).
Now let’s look at who is behind each of those numbers.
Endpoint: POST /v3/comments
Returns the replies posted under a specific tweet. Each page contains up to 20 comments, and each comment is a full tweet object with its own engagement metrics and author profile.
Simplest Example
def get_comments(tweet_link):
resp = requests.post(
"https://api.sorsa.io/v3/comments",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json={"tweet_link": tweet_link},
)
resp.raise_for_status()
return resp.json()
data = get_comments("https://x.com/elonmusk/status/1234567890")
for comment in data.get("tweets", []):
print(f"@{comment['user']['username']}: {comment['full_text'][:80]}")
Parameters
| Parameter | Type | Required | Description |
|---|
tweet_link | string | Yes | Full URL of the tweet. |
next_cursor | string | No | Pagination cursor for fetching more comments. |
Tweets with hundreds of replies require pagination. The pattern is the same cursor-based loop used across all Sorsa endpoints:
import time
def get_all_comments(tweet_link, max_pages=20):
"""Fetch all comments under a tweet with pagination."""
all_comments = []
next_cursor = None
for page in range(max_pages):
body = {"tweet_link": tweet_link}
if next_cursor:
body["next_cursor"] = next_cursor
resp = requests.post(
"https://api.sorsa.io/v3/comments",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json=body,
)
resp.raise_for_status()
data = resp.json()
comments = data.get("tweets", [])
all_comments.extend(comments)
next_cursor = data.get("next_cursor")
if not next_cursor:
break
time.sleep(0.1)
return all_comments
comments = get_all_comments("https://x.com/elonmusk/status/1234567890")
print(f"Collected {len(comments)} comments")
Each comment is a full tweet object, so you have the text, engagement metrics, and author profile. This unlocks several analysis patterns:
Sentiment analysis. Feed the full_text of each comment into an NLP classifier to gauge whether replies are positive, negative, or neutral. A tweet with 500 replies that are 80% negative tells a very different story than one with 500 positive replies.
Identify top commenters. Sort by likes_count to find the most-engaged-with replies. These are the voices that shaped the conversation.
Extract questions. Filter comments containing ”?” to find questions your audience is asking - useful for FAQ generation, content ideas, and customer support detection.
# Find the most-liked comments
top_comments = sorted(comments, key=lambda c: c.get("likes_count", 0), reverse=True)
print("Top 5 comments by likes:")
for c in top_comments[:5]:
print(f" @{c['user']['username']} ({c['likes_count']} likes): {c['full_text'][:80]}")
Endpoint: POST /v3/quotes
Returns tweets that quoted (retweeted with comment) a specific tweet. Like comments, each quote is a full tweet object - you get the added commentary, engagement metrics, and author profile.
Simplest Example
def get_quotes(tweet_link):
resp = requests.post(
"https://api.sorsa.io/v3/quotes",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json={"tweet_link": tweet_link},
)
resp.raise_for_status()
return resp.json()
data = get_quotes("https://x.com/elonmusk/status/1234567890")
for quote in data.get("tweets", []):
print(f"@{quote['user']['username']} quoted: {quote['full_text'][:80]}")
Parameters
| Parameter | Type | Required | Description |
|---|
tweet_link | string | Yes | Full URL of the original tweet. |
next_cursor | string | No | Pagination cursor. |
Paginating Through All Quotes
def get_all_quotes(tweet_link, max_pages=20):
"""Fetch all quote tweets of a specific tweet."""
all_quotes = []
next_cursor = None
for page in range(max_pages):
body = {"tweet_link": tweet_link}
if next_cursor:
body["next_cursor"] = next_cursor
resp = requests.post(
"https://api.sorsa.io/v3/quotes",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json=body,
)
resp.raise_for_status()
data = resp.json()
quotes = data.get("tweets", [])
all_quotes.extend(quotes)
next_cursor = data.get("next_cursor")
if not next_cursor:
break
time.sleep(0.1)
return all_quotes
A retweet is passive amplification - the user pressed a button. A quote tweet is active engagement - the user added their own take, and that take is visible to their entire audience. Quotes often contain the most valuable signal: endorsements, criticisms, counterarguments, and derivative ideas. For content analysis and PR monitoring, quote tweets are where the real conversation happens.
quotes = get_all_quotes("https://x.com/brand/status/1234567890")
# Find quotes that reached the largest audiences
quotes.sort(key=lambda q: q["user"].get("followers_count", 0), reverse=True)
print("Quotes from the highest-reach accounts:")
for q in quotes[:5]:
u = q["user"]
print(f" @{u['username']} ({u['followers_count']:,} followers)")
print(f" \"{q['full_text'][:80]}...\"\n")
Endpoint: POST /v3/retweets
Returns the users who retweeted a specific tweet. Note: unlike /comments and /quotes, this endpoint returns a UsersResponse (array of user profiles), not a TweetsResponse. You get the retweeters’ profiles, not tweet objects.
Simplest Example
def get_retweeters(tweet_link):
resp = requests.post(
"https://api.sorsa.io/v3/retweets",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json={"tweet_link": tweet_link},
)
resp.raise_for_status()
return resp.json()
data = get_retweeters("https://x.com/elonmusk/status/1234567890")
for user in data.get("users", []):
print(f"@{user['username']} ({user['followers_count']} followers) retweeted")
Parameters
| Parameter | Type | Required | Description |
|---|
tweet_link | string | Yes | Full URL of the tweet. |
next_cursor | string | No | Pagination cursor. |
This is the key distinction to remember:
| Endpoint | Returns | Response key | Contains |
|---|
/comments | Tweets | tweets | Full tweet objects (text + author) |
/quotes | Tweets | tweets | Full tweet objects (text + author) |
/retweets | Users | users | User profile objects only |
Retweets do not have their own text (a retweet is just a redistribution of the original), so the endpoint returns the profile of each retweeter instead.
def get_all_retweeters(tweet_link, max_pages=20):
"""Fetch all users who retweeted a tweet."""
all_users = []
next_cursor = None
for page in range(max_pages):
body = {"tweet_link": tweet_link}
if next_cursor:
body["next_cursor"] = next_cursor
resp = requests.post(
"https://api.sorsa.io/v3/retweets",
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json=body,
)
resp.raise_for_status()
data = resp.json()
users = data.get("users", [])
all_users.extend(users)
next_cursor = data.get("next_cursor")
if not next_cursor:
break
time.sleep(0.1)
return all_users
Since you get full user profiles, you can analyze who amplified the tweet:
retweeters = get_all_retweeters("https://x.com/brand/status/1234567890")
total_reach = sum(u.get("followers_count", 0) for u in retweeters)
verified_count = sum(1 for u in retweeters if u.get("verified"))
print(f"Retweeters: {len(retweeters)}")
print(f"Combined follower reach: {total_reach:,}")
print(f"Verified retweeters: {verified_count}")
Combining all three endpoints gives you a complete picture of how a tweet performed - not just the numbers, but the people and content behind them:
def full_engagement_report(tweet_link):
"""Generate a complete engagement report for a single tweet."""
# Get tweet metrics
tweet = get_tweet(tweet_link)
print(f"Tweet by @{tweet['user']['username']}:")
print(f" \"{tweet['full_text'][:100]}...\"")
print(f" Likes: {tweet.get('likes_count', 0):,} | "
f"Views: {tweet.get('view_count', 0):,}")
print()
# Comments
comments = get_all_comments(tweet_link, max_pages=10)
print(f"Comments: {len(comments)}")
if comments:
top_comment = max(comments, key=lambda c: c.get("likes_count", 0))
print(f" Most liked: @{top_comment['user']['username']} "
f"({top_comment['likes_count']} likes)")
print(f" \"{top_comment['full_text'][:80]}...\"")
print()
# Quotes
quotes = get_all_quotes(tweet_link, max_pages=10)
print(f"Quotes: {len(quotes)}")
if quotes:
biggest_quoter = max(quotes, key=lambda q: q["user"].get("followers_count", 0))
print(f" Highest reach: @{biggest_quoter['user']['username']} "
f"({biggest_quoter['user']['followers_count']:,} followers)")
print(f" \"{biggest_quoter['full_text'][:80]}...\"")
print()
# Retweeters
retweeters = get_all_retweeters(tweet_link, max_pages=10)
total_reach = sum(u.get("followers_count", 0) for u in retweeters)
print(f"Retweeters: {len(retweeters)}")
print(f" Combined reach: {total_reach:,} followers")
if retweeters:
top_rt = max(retweeters, key=lambda u: u.get("followers_count", 0))
print(f" Biggest amplifier: @{top_rt['username']} "
f"({top_rt['followers_count']:,} followers)")
return {
"tweet": tweet,
"comments": comments,
"quotes": quotes,
"retweeters": retweeters,
}
report = full_engagement_report("https://x.com/brand/status/1234567890")
Sample Output
Tweet by @brand:
"We're excited to announce our Series B funding round of $50M..."
Likes: 2,847 | Views: 892,000
Comments: 156
Most liked: @tech_journalist (89 likes)
"Congrats! What's the plan for international expansion?..."
Quotes: 43
Highest reach: @vc_partner (284,000 followers)
"This team has been on our radar for two years. Well deserved...."
Retweeters: 312
Combined reach: 4,218,000 followers
Biggest amplifier: @industry_leader (892,000 followers)
When you need engagement data for a set of tweets (e.g., all posts from a campaign), fetch the tweet list first via /user-tweets or /search-tweets, then drill into each one:
def compare_tweet_engagement(tweet_links):
"""Compare engagement breakdown across multiple tweets."""
results = []
for link in tweet_links:
tweet = get_tweet(link)
comments = get_all_comments(link, max_pages=3)
quotes = get_all_quotes(link, max_pages=3)
retweeters = get_all_retweeters(link, max_pages=3)
rt_reach = sum(u.get("followers_count", 0) for u in retweeters)
results.append({
"text": tweet["full_text"][:60],
"likes": tweet.get("likes_count", 0),
"comments": len(comments),
"quotes": len(quotes),
"retweets": len(retweeters),
"retweet_reach": rt_reach,
})
time.sleep(0.5)
# Print comparison
print(f"{'Tweet':<62} {'Likes':>6} {'Cmts':>5} {'Qts':>4} {'RTs':>4} {'RT Reach':>10}")
print("-" * 100)
for r in results:
print(f"{r['text']:<62} {r['likes']:>6} {r['comments']:>5} "
f"{r['quotes']:>4} {r['retweets']:>4} {r['retweet_reach']:>10,}")
return results
This is useful for identifying which tweets in a series performed best and understanding why - did success come from comments (conversation), quotes (endorsement/debate), or retweets (amplification)?
Tip: If you just need the aggregate metrics for many tweets without drilling into individual comments/quotes/retweeters, use /tweet-info-bulk to fetch up to 100 tweets in a single request. See Optimizing API Usage for more batch patterns.
Exporting Engagement Data to CSV
import csv
def export_comments_to_csv(comments, output_file="comments.csv"):
fields = [
"comment_id", "created_at", "full_text", "likes", "retweets",
"author_username", "author_followers", "author_verified",
]
with open(output_file, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
for c in comments:
u = c.get("user", {})
writer.writerow({
"comment_id": c["id"],
"created_at": c["created_at"],
"full_text": c["full_text"],
"likes": c.get("likes_count", 0),
"retweets": c.get("retweet_count", 0),
"author_username": u.get("username", ""),
"author_followers": u.get("followers_count", 0),
"author_verified": u.get("verified", False),
})
print(f"Exported {len(comments)} comments to {output_file}")
The same pattern works for quotes (they are also tweet objects). For retweeters, export user fields instead of tweet fields.
Verification Endpoints: Did a Specific User Engage?
If you need to check whether a particular user commented on, quoted, or retweeted a tweet (common in campaign and giveaway verification), Sorsa provides dedicated verification endpoints that return a simple yes/no answer without paginating through the full list:
/check-comment - did a specific user reply to the tweet?
/check-quoted - did they quote it?
/check-retweet - did they retweet it?
These are covered in depth in the Marketing Campaign Verification guide.
Next Steps
- Search Tweets - find tweets by keyword, then drill into their engagement.
- Track Mentions - monitor mentions of your brand, then analyze engagement on the most-discussed ones.
- Competitor Analysis - compare engagement patterns across competitor content.
- Historical Data - retrieve old tweets and analyze how their engagement played out.
- Marketing Campaign Verification - verify that specific users commented on or retweeted a tweet.
- API Reference - full specification for
/comments, /quotes, /retweets, /tweet-info, /tweet-info-bulk.