Skip to content

USE CASE

Twitter API for Competitor Analysis

Updated July 2026

How do you run competitor analysis on Twitter (X) with an API?

The Twitter API is a set of REST endpoints that return any public account's posts, profile and follower graph, which is everything a competitor benchmark needs. Pull each rival's timeline and profile over one bounded window, compute posting cadence and engagement rate per post, add a search query per brand to capture unprompted market commentary, and take a follower set difference when you want the audience gap. TwitterAPIs bills every read at $0.0008 with no developer account and one flat ceiling of 600 requests a minute per key.

How the numbers on this page were produced

Written by Emma, TwitterAPIs developer relations

Costs are call arithmetic against the flat $0.0008 per read call on our published pricing. Where a figure counts records rather than calls, the yield it assumes is stated beside it: timeline reads returned, per our own billed-call measurement, 18.78 posts per call on average across 396,817 read calls between August 13 and 17 2026, and follower pages return about 70 records on the first page and fewer after it.

Seven questions, and the call that answers each one

Competitor analysis goes wrong when it becomes a dashboard nobody acts on. Start from the question rather than the metric. These seven are the ones that have changed a decision, ordered from cheapest to answer to most expensive.

QuestionEndpointReadsWhat you get
How often do they post, and whenGET /twitter/user/tweetsOne paged pull per rivalPosts per week and the hours their best posts land
What actually works for themGET /twitter/user/tweetsSame pull, sorted by engagement rateTheir top posts, which is their content strategy stated as evidence
Is their audience realGET /twitter/user/infoOne call per rivalFollowers against engagement, which exposes a bought audience quickly
Who follows them but not youGET /twitter/user/followersPaged, the most expensive question hereThe audience gap, and a targeting list
What is the market saying about themGET /twitter/tweet/advanced_searchOne query per rival per intervalUnprompted mentions, complaints and comparisons
Did they just ship somethingGET /twitter/user/tweetsShort poll on a scheduleLaunch detection, usually hours before it reaches a newsletter
How did the market reactGET /twitter/tweet/replies, GET /twitter/tweet/quotesOn the launch postObjections in public, which is competitive research nobody has to run

Build a benchmark table across a competitive set

This pulls every rival over one shared window, drops posts too young to have finished accruing engagement, and reports mean and median engagement rate side by side so a single viral post cannot pass as consistent performance.

import requests, statistics
from datetime import datetime, timedelta, timezone

BASE = "https://api.twitterapis.com/twitter"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

# A post keeps accruing engagement for days. Anything younger than this has
# not finished, and mixing it with mature posts corrupts the comparison.
MATURITY = timedelta(hours=48)

def profile(user_name):
    res = requests.get(f"{BASE}/user/info", params={"userName": user_name},
                       headers=HEADERS, timeout=30).json()
    return res.get("user") or {}

def timeline(user_name, pages=10):
    out, cursor = [], None
    for _ in range(pages):
        params = {"userName": user_name}
        if cursor:
            params["cursor"] = cursor
        res = requests.get(f"{BASE}/user/tweets", params=params,
                           headers=HEADERS, timeout=30).json()
        out += res.get("tweets") or []
        if not res.get("has_more"):
            break
        cursor = res.get("next_cursor")
    return out

def benchmark(handles, weeks=4):
    cutoff = datetime.now(timezone.utc) - timedelta(weeks=weeks)
    mature_before = datetime.now(timezone.utc) - MATURITY
    rows = {}

    for handle in handles:
        who = profile(handle)
        followers = max(who.get("followers_count") or 0, 1)
        rates, posts = [], 0

        for tweet in timeline(handle):
            created = datetime.strptime(
                tweet["createdAt"], "%a %b %d %H:%M:%S %z %Y")
            if created < cutoff:
                continue
            posts += 1
            if created > mature_before:      # too young to score
                continue
            engagement = ((tweet.get("likeCount") or 0)
                          + (tweet.get("retweetCount") or 0)
                          + (tweet.get("replyCount") or 0))
            rates.append(100 * engagement / followers)

        rows[handle] = {
            "followers": followers,
            "posts_per_week": round(posts / weeks, 1),
            "mean_rate": round(statistics.mean(rates), 3) if rates else 0.0,
            "median_rate": round(statistics.median(rates), 3) if rates else 0.0,
            "scored": len(rates),
        }
    return rows

for handle, row in benchmark(["rival_a", "rival_b", "our_handle"]).items():
    # A mean far above the median means one post carried the account.
    print(f"{handle:<12} {row['followers']:>9,} followers  "
          f"{row['posts_per_week']:>5}/wk  "
          f"mean {row['mean_rate']:>6}%  median {row['median_rate']:>6}%")

The maturity filter is the detail that makes the table trustworthy. Engagement keeps accruing for days after a post, so including yesterday's posts alongside last month's understates the recent ones and makes any account look like it is declining. Every rival is also pulled over one shared window, for the same reason.

Four metrics worth benchmarking, and the trap in each

MetricHow to compute itWhy it earns its placeThe trap
Engagement rate per postLikes plus reposts plus replies, divided by follower countThe only cross-account comparison that survives a size differenceA rival with a small, tight audience will beat a large one, which is the point
Posting cadencePosts per week over a bounded windowSeparates a strategy from a burst nobody sustainedMeasure over at least four weeks, or one launch week reads as their norm
Reply ratioReplies over total postsShows whether they run an audience or a broadcast channelNeeds tweets_and_replies, since the plain timeline hides most replies
Median rather than mean engagementThe middle post, not the average postOne viral post makes a mediocre account look excellent on a meanReport both, and treat a large gap between them as the finding

Reply ratio needs user/tweets_and_replies rather than the plain timeline, because the default view hides most replies and will report a conversational account as a broadcast one.

The audience gap, and what it costs to measure

The most actionable competitor question is which accounts follow a rival and not you. It is also the only expensive one on this page, because follower lists are cursor-paged at roughly 70 records on the first page and fewer after it, so a rival with 50,000 followers is about 700 calls, near $0.56 at $0.0008 each.

Page both lists with GET /twitter/user/followers, take the set difference on user id, then resolve only the accounts that clear a size or activity floor. Resolving all of them is the mistake, because the long tail of a follower list is mostly dormant and costs one profile call each to discover that.

Run it monthly rather than continuously and store the result, so the next pass reconciles a change rather than rebuilding the whole list. The mechanics of cursor paging, page sizes and the v1 against v2 response shapes are covered on the Twitter followers API page.

Detecting a rival launch before the newsletters do

A launch post does not announce itself in its text, it announces itself in its slope. Hold a trailing median engagement figure per rival, poll their timeline every 15 minutes, and flag any post whose first-hour engagement runs several times that median. On most accounts this fires hours before a press cycle or a newsletter picks it up.

When it fires, pull tweet/replies and tweet/quotes on that post. The replies are the market objecting in public, unprompted and unfiltered, which is competitive research nobody had to commission. Feeding those into a scoring pass gives you the reaction as a number as well as a transcript, which is a sentiment pipeline pointed at somebody else.

A five-rival watcher at 15-minute cadence is 480 calls a day, roughly $0.38 a day, about $11.68 a month, which is a rounding error against the cost of finding out late.

By the numbers

Competitor benchmarking on X, by the numbers

TwitterAPIs figures resolve to our published pricing and our own billed-call measurements. Every X figure is vendor-documented.

  • TwitterAPIs bills every timeline, profile and search call at a flat $0.0008, with no plan tier and no per-competitor fee. (TwitterAPIs pricing, 2026)

  • Across 396,817 billed read calls measured August 13 to 17 2026, account timeline reads returned 18.78 posts per call on average, close to the full 20-post page the published per-1,000 figure assumes. (TwitterAPIs billed-call measurement, 2026)

  • Follower pages return about 70 records on the first page and fewer after, so a 50,000-follower audience gap costs roughly 700 calls, near $0.56. (TwitterAPIs pricing, 2026)

  • A new account starts with $0.50 in credit and no card, enough to benchmark a five-rival set many times over before you spend anything. (TwitterAPIs pricing, 2026)

  • The official X API meters post reads from about $0.005 per resource, one item per request, under its pay-per-use model. (X Developer Platform, 2026)

  • The official X API enforces per-endpoint rate limits in fixed 15-minute windows, and pay-per-use is hard-capped at 3 million reads per monthly billing cycle. (X API docs, 2026)

Competitor analysis, common questions

Pull each rival's timeline with GET /twitter/user/tweets and their profile with GET /twitter/user/info, then compute posting cadence and engagement rate per post over the same bounded window for everyone in the set. Add GET /twitter/tweet/advanced_search on each brand name to capture what the market says about them unprompted, and GET /twitter/user/followers when you want the audience overlap. Every call is a flat $0.0008, so a five-rival benchmark refreshed weekly costs a few cents a month.

Yes. Poll each rival's timeline on a short interval and flag any post whose engagement in its first hour runs well above their trailing median. Launch posts stand out on that measure long before they reach a newsletter or a press cycle. A five-rival watcher at 15-minute cadence is 480 calls a day, roughly $0.38 a day or about $11.68 a month, and the replies and quote tweets under the flagged post give you the market's objections in their own words.

A weekly benchmark across five rivals, pulling ten timeline pages and one profile call each, is about 55 calls a run, roughly four cents a week. Adding a mention query per rival at hourly cadence brings it to about 3,600 calls a month, near $2.88. The follower-overlap pull is the one expensive item, and it is a monthly job rather than a continuous one. There is no plan tier and no per-competitor fee.

The API returns public posts and public profile fields only, which is the same data any person browsing x.com can see. Protected accounts and direct messages are not available through it. That said, what you may do with data you have collected is governed by the platform terms and by the privacy law where you operate, so treat the collection step and the use step as separate questions and take advice on the second one.

Use engagement rate rather than raw counts: likes plus reposts plus replies on a post, divided by the account's follower count. Raw engagement only tells you who is bigger, which you already knew. Rate tells you whose audience actually responds, and it is common for a smaller account with a tight niche audience to beat a much larger rival on this measure. Report the median post alongside the mean, because a single viral post drags a mean upward and hides an otherwise flat account.

Page GET /twitter/user/followers for the rival and for your own account, then take the set difference. Follower pulls are cursor-paged and return about 70 records on the first page and fewer after, so this is the most expensive question on the page: a rival with 50,000 followers is roughly 700 calls, about $0.56. Run it monthly rather than continuously, and store the result so the next run only has to reconcile the change.

GET /twitter/user/tweets pages back through an account's timeline by cursor, and GET /twitter/user/tweets/complete pulls the full account history in one job at $0.0024 a call. For a benchmark, four to twelve weeks is usually enough and much cheaper than a full history, because cadence and engagement rate both stabilise over that window while a full archive mostly adds posts nobody will read.

Almost always because the windows differ. Engagement on a post keeps accruing for days, so a post read six hours after publishing and a post read six days after publishing are not comparable measurements, and averaging them produces a number that is arithmetically clean and meaningless. Pin every account in the set to the same since and until bounds, and exclude posts younger than your maturity threshold from any rate calculation.

Related use cases

Widen the same queries past the named set and you are running social listening. Mine a rival's unhappy replies for prospects and it becomes lead generation. Vet the creators in their orbit and it becomes influencer discovery. All fourteen are indexed on the Twitter API use cases hub.

Benchmark your competitive set this week

$0.0008 per call, $0.50 in free credit, no card and no X developer account.