Twitter (X) Competitor Analysis — A Developer's API Guide
Competitor analysis on Twitter (X) is one of the most common dev workflows around social-data APIs — benchmark your account against rivals, identify content patterns that drive engagement, spot the hashtags they own, track posting cadence. Dashboard tools (Brand24, Sprout Social, Tweet Binder) sell this as a UI; the dev-built version costs less and is custom to your specific metrics.
This guide walks the API workflow with runnable Python: pull each competitor's profile + recent tweets, aggregate client-side, and persist for trend analysis. Per-call cost math derives from each provider's published pricing page so you can budget.
What 'competitor analysis' decomposes into
Six common metrics that production competitor-analysis workflows compute:
- Follower growth rate — delta(followers_count) / period, captured from daily snapshots
- Posting cadence — tweets per day or per week, derived from recent-tweets timeline
- Engagement rate — mean of (likes + retweets + replies) / followers × 100 across recent tweets (public-data approximation; full formula needs OAuth)
- Hashtag overlap — count of #tags used by competitor vs your own — surfaces topics they own that you don't
- Mention graph — who they reply to or quote, surfaces their network ties
- Posting time-of-day distribution — when they post, useful for scheduling against (or with) their windows
Step 1 — fetch each competitor's profile
Profile read gives you follower count + denominator for engagement rate. twitterapi.io's /twitter/user/info, X official's /2/users/by/username.
Per twitterapi.io/pricing: $0.00018 per profile read. Per docs.x.com pricing: $0.010.
import os, requests
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
def profile(username: str) -> dict:
r = requests.get(
f"{BASE}/twitter/user/info",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
r.raise_for_status()
return r.json()
for u in ["twitterapi_io", "competitor_a", "competitor_b"]:
p = profile(u)
print(f"{u}: {p.get('followers_count')} followers")
Step 2 — fetch recent tweets for each competitor
Recent-tweets timeline gives you engagement numerator + posting cadence + hashtag usage. twitterapi.io's /twitter/user/last_tweets returns recent tweets with public_metrics per tweet.
Per twitterapi.io/pricing: $0.00015 per returned tweet.
def recent_tweets(username: str) -> list:
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", [])
for u in ["twitterapi_io", "competitor_a"]:
tweets = recent_tweets(u)
print(f"{u}: {len(tweets)} recent tweets")
Step 3 — aggregate client-side into competitor metrics
Once you have profiles + tweets, the analytics work happens in your code:
Posting cadence: count tweets in last 7 days from each competitor.
Engagement rate (public approximation): for each competitor, mean((like_count + retweet_count + reply_count) / followers × 100) across recent tweets.
Hashtag set: extract #tag patterns from each competitor's tweet bodies; compute set difference to find tags they use that you don't.
Mention graph: extract @user mentions per competitor; aggregate top mentions per account.
Time-of-day distribution: bucket created_at by hour for each competitor.
Side-by-side comparison — 3 paths, 5 dimensions
Same job (competitor analysis benchmarking) framed across three paths. Costs derived from cited pricing.
Three patterns: (a) per-call cost compounds — 10 competitors × daily snapshot at twitterapi.io is single-digit-dollar monthly; (b) dashboard tools win on plug-and-play but lose on custom-metric flexibility; (c) production teams often run both — dashboard for stakeholder reports + twitterapi.io for internal product analytics.
Persistence + trend analysis
Counter values and engagement metrics today don't mean much in isolation — the trend over time is the operationally useful signal. Persist snapshots daily:
Storage shape: (competitor, captured_at, followers, posting_cadence_7d, engagement_rate_pct, top_hashtags) row per competitor per day.
Trend metrics to compute: follower growth rate (delta per period), engagement-rate trend (rolling 28-day mean), posting cadence change (week-over-week).
Anomaly detection: alert when any competitor's follower delta exceeds 2× their normal weekly rate (something they did is working — investigate).
Storage cap: at daily cadence × 10 competitors × 365 days = 3,650 rows per year. Small dataset; SQLite or Postgres both fine.
Picking a path — the decision rule
Building competitor-analytics into your own product (analytics tool, growth dashboard, BI feature)? → twitterapi.io. Per-call cost makes wide-coverage tracking economically viable.
Already on the X bill, competitor analysis is one workflow among many? → X official; marginal cost rides on same auth.
Need a polished UI for non-technical stakeholders (founders, marketing leads)? → Dashboard tool — Sprout Social or Brand24. Pay the seat fee, get a polished report.
Most production stacks pair: Sprout/Brand24 (stakeholder reports) + twitterapi.io (programmatic benchmark layer). They answer different questions.
# Practical example: snapshot N competitors daily, compute engagement-rate + hashtag overlap.
import os, requests, re
from collections import Counter
from datetime import datetime, timezone
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
HASHTAG_RE = re.compile(r"#(\w+)")
def competitor_snapshot(username: str) -> dict:
p = requests.get(f"{BASE}/twitter/user/info", headers=HEADERS, params={"userName": username}, timeout=10).json()
t = requests.get(f"{BASE}/twitter/user/last_tweets", headers=HEADERS, params={"userName": username}, timeout=10).json()
tweets = t.get("data", [])
followers = p.get("followers_count", 0)
if followers == 0 or not tweets:
return {"username": username, "error": "insufficient data"}
engagements = []
hashtags = Counter()
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)
engagements.append(eng / followers * 100)
for tag in HASHTAG_RE.findall(tw.get("text", "")):
hashtags[tag.lower()] += 1
return {
"username": username,
"captured_at": datetime.now(timezone.utc).isoformat(),
"followers": followers,
"mean_engagement_pct": round(sum(engagements) / len(engagements), 4),
"top_hashtags": hashtags.most_common(5),
"posting_cadence_recent": len(tweets),
}
for u in ["twitterapi_io", "competitor_a", "competitor_b"]:
print(competitor_snapshot(u))
# Cost framing (math from cited pricing pages):
# 1 profile + 30 tweets per competitor = $0.00018 + 30 * $0.00015 = $0.00468
# 3 competitors × daily × 30 days = $0.42/mo at twitterapi.io rates
# Same workload via X official: 3 × ($0.010 + 30 × $0.005) × 30 = $14.40/mo (~34x more)Questions readers ask
How many competitors should I track?
Depends on your analysis goal. Most production benchmarking workflows track 5-15 competitors. More than 30 dilutes the comparative signal (the long tail is mostly noise); fewer than 3 may not give a meaningful peer baseline. Adjust by your industry's competitive density.
How does this differ from generic 'social listening'?
Social listening surfaces mentions across the web around your brand or keywords. Competitor analysis is targeted — you're benchmarking specific accounts' performance metrics over time. Both can be built on the same APIs but the workflows differ: listening is keyword-search-driven; competitor analysis is account-driven.
Can I track competitor hashtag campaigns?
Yes — combine the profile-snapshot workflow above with a hashtag-search workflow using /twitter/tweet/advanced_search?query=#campaign_tag. The hashtag-search returns tweets from anyone, including the competitor running the campaign and the audience engaging with it. Useful for measuring campaign reach + response.
What's a reasonable refresh cadence?
Daily is sufficient for most counter + engagement metrics. Hashtag activity tends to be event-driven (campaigns, news) so hourly or 15-min cadence catches campaign moments more precisely. Set the cadence per workflow.
How do I handle competitor accounts that go private?
Protected / private accounts return limited data — counters may still be visible but recent-tweets read returns nothing. Log this as the operationally important event and pause tracking until the account goes public again.
Is competitor analysis OK under X's terms?
Reading public profile + public-tweet data via API is the standard workflow X's developer terms cover. Avoid scraping, storing user-personal data, or building products that violate X's developer agreement. When in doubt, consult docs.x.com/developer-terms for the current policy.
Continue
- Twitter (X) API — cluster hub
- Twitter (X) profile analytics API guide
- Twitter (X) hashtag analytics API guide
- Twitter (X) analytics tools — comparison
- 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