How to Calculate Twitter (X) Engagement Rate via API
Twitter (X) engagement rate is the standard cross-network metric for tweet performance — a single number summarizing how much your audience interacted with each post. The textbook formula is simple, but the data-availability constraints around impressions (non-public, OAuth-only) make the operational implementation more nuanced. This guide walks the formula, the data fetch via API, and runnable Python.
Two flavors of the calculation: full-metric (when you have impressions — your own account only) and public-data approximation (when you don't — competitor or third-party account monitoring). The code below implements both. Pricing references are URL-cited and the multipliers derive from each provider's published rates.
The formula — engagement rate, full and approximate
Per-tweet engagement rate (full):
rate = (like_count + retweet_count + reply_count + quote_count) / impression_count × 100
Per-tweet engagement rate (public-data approximation):
rate ≈ (like_count + retweet_count + reply_count + quote_count) / follower_count × 100
The second form substitutes follower count for impressions because impressions are non-public (OAuth user-context only). It systematically over-estimates rate (follower count > impression count for most tweets) but is the canonical workaround for analyzing accounts you don't own.
Account-level engagement rate is the mean of per-tweet rates across the N most recent tweets (or the N tweets in the last 30 days, depending on your reporting cadence). The mean across many tweets smooths out outliers; the median is more robust when one tweet went viral.
Step 1 — fetch the user's profile (for follower count)
Profile read gives you the denominator for the approximation. twitterapi.io's /twitter/user/info returns the public-metrics record including followers_count.
Pricing per twitterapi.io/pricing: $0.00018 per profile read. X official: $0.010 per profile read per docs.x.com/x-api/getting-started/pricing.
import os, requests
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
def get_followers(username: str) -> int:
r = requests.get(
f"{BASE}/twitter/user/info",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
r.raise_for_status()
return r.json().get("followers_count", 0)
followers = get_followers("twitterapi_io")
print(f"followers: {followers}")
Step 2 — fetch recent tweets (for engagement numerator)
Pull the recent tweet timeline with public_metrics. twitterapi.io's /twitter/user/last_tweets returns recent tweets with the public_metrics record per tweet.
Each returned tweet is $0.00015 at twitterapi.io rates, $0.005 at X official rates.
def get_recent_tweets(username: str):
r = requests.get(
f"{BASE}/twitter/user/last_tweets",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
r.raise_for_status()
return r.json().get("data", [])
tweets = get_recent_tweets("twitterapi_io")
for t in tweets[:3]:
pm = t.get("public_metrics", {})
eng = pm.get("like_count", 0) + pm.get("retweet_count", 0) + pm.get("reply_count", 0) + pm.get("quote_count", 0)
print(f" {t['id']}: total engagement = {eng}")
Step 3 — compute engagement rate per tweet + account-level
Combine the followers count with each tweet's engagement to get the approximate rate. The full formula (with impressions) requires OAuth user-context — show both paths in code.
Account-level metrics summarize across the recent set; report mean, median, p90 to give a sense of distribution. Outliers (one viral tweet) skew the mean meaningfully.
Side-by-side comparison — 3 paths to engagement metrics
Same job (calculate engagement rate for an account) framed across three paths. Costs derived from each provider's published pricing.
Three patterns: (a) impressions are the non-public-metric constraint — any path that needs the full formula must use X official with user-context auth on your own account; (b) public-data approximation (engagement / followers) works for all paths and is the canonical workaround for accounts you don't own; (c) per-call cost compounds at scale — for analyzing many accounts, twitterapi.io's per-call rate dominates.
Reporting — what to render and what to compare against
Once you have per-tweet rates, the reporting layer typically shows:
- Account-level rate over time — weekly or monthly average, plotted as a line chart, with rolling 4-week mean overlaid
- Top-engagement tweets — leaderboard of the highest-rate posts in the period
- Distribution — histogram of per-tweet rates so the user sees how concentrated their engagement is in a few viral posts
- Cross-account comparison — for competitive analysis, repeat the workflow for N tracked competitors and overlay their rates on the same chart
Industry benchmarks vary by sector and follower count — a Fortune-500 brand and a single-creator account have very different baselines. Calibrate against your own captured data and your peers.
Picking a path — the decision rule
Calculating your own account's rate with impressions? → X official OAuth user-context. Only path that returns non-public impression count for full-formula computation.
Calculating competitor or third-party account rates (public-data approximation)? → twitterapi.io. Per-call cost is the lowest of the three at any non-trivial volume; same data return shape as X official.
Already on the X bill? → X official bearer for the same approximation; marginal cost rides on the same auth.
Most analytics products combine paths: X user-context for the customer's own accounts (full formula), twitterapi.io for competitor and benchmark accounts (approximation). Per-call pricing makes wide-coverage analytics economically viable.
# Practical example: compute engagement rate for an account from N recent tweets.
# Uses public-data approximation (engagement / followers).
import os, requests, statistics
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
def calculate_engagement_rate(username: str):
# Profile fetch — for follower count denominator
p = requests.get(
f"{BASE}/twitter/user/info",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
p.raise_for_status()
profile = p.json()
followers = profile.get("followers_count", 0)
if followers == 0:
return None
# Recent tweets fetch
t = requests.get(
f"{BASE}/twitter/user/last_tweets",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
t.raise_for_status()
tweets = t.json().get("data", [])
if not tweets:
return None
rates = []
for tw in tweets:
pm = tw.get("public_metrics", {})
eng = (
pm.get("like_count", 0)
+ pm.get("retweet_count", 0)
+ pm.get("reply_count", 0)
+ pm.get("quote_count", 0)
)
rate = eng / followers * 100
rates.append(rate)
return {
"username": username,
"followers": followers,
"n_tweets": len(rates),
"mean_rate_pct": round(statistics.mean(rates), 4),
"median_rate_pct": round(statistics.median(rates), 4),
"max_rate_pct": round(max(rates), 4),
}
result = calculate_engagement_rate("twitterapi_io")
print(result)
# Cost framing (math from cited pricing pages):
# 1 profile + ~20 tweets = $0.00018 + 20 × $0.00015 = $0.00318 per account
# Same workload via X official: $0.010 + 20 × $0.005 = $0.11 (~35x more)
# For 1,000 tracked accounts daily: ~$3.18/day vs $110/day. Compounds favorably.
# Note: impressions field is non-public; the formula above uses follower-count
# as the denominator (public-data approximation). For the full formula
# (with real impressions), use X official with OAuth user-context on your own account.Questions readers ask
Why can't I get impressions for accounts I don't own?
Per docs.x.com, impressions are a non-public metric — they require OAuth user-context auth, which scopes the request to a specific account owner. You can fetch your own non-public metrics but not someone else's. The standard workaround for cross-account analysis is the public-data approximation (engagement / followers).
Is the public-data approximation accurate?
It systematically over-estimates the engagement rate because follower count is always larger than impression count for any given tweet (not all followers see every tweet). For relative comparison (account A vs account B) it's directionally useful; for absolute reporting against industry benchmarks, the absolute number is inflated.
What's a good engagement rate?
Industry benchmarks vary widely by sector and follower count. Common rough rules: 0.5-1% is typical for general accounts, 1-3% is good, >3% is exceptional. Larger accounts trend lower (more followers to divide engagement across). Calibrate against peer accounts in your own niche rather than against universal benchmarks.
Should I include bookmarks in the engagement numerator?
Bookmark counts are surfaced on some endpoints when available — include them if your accounts consistently see bookmark engagement. For most public reporting bookmarks are a recent addition and the convention is to include likes + retweets + replies + quotes as the canonical engagement metrics.
How do I monitor engagement-rate over time?
Snapshot the calculation daily and persist the result. A simple (username, captured_at, n_tweets, mean_rate, median_rate) row layout in your warehouse builds a time-series. Plot weekly or monthly mean for trend visibility.
Can I batch many accounts in one workflow?
Yes — loop the calculation across your tracked accounts. Math: 100 accounts × ~$0.003 each = $0.30 per refresh via twitterapi.io. Daily refresh for a month = $9. Same workload via X official rates is ~$330/month.
Continue
- twitterapi.io — pricing
- X API — pricing (docs.x.com, 2026 verified)
- X — Metrics (public vs non-public)
- Twitter (X) API — cluster hub
- Twitter (X) stats API — public/private metrics
- Twitter (X) profile analytics API guide
- Twitter (X) analytics tools — dev roundup
- twitterapi.io pricing
Stop reading. Start building.
Starter credits cover real testing on real data. Google sign-in, no card, no application queue.
Get an API key