twitterapi.io is an independent third-party service. Not affiliated with X Corp.

Blogtwitter stats

Twitter (X) Stats API — Three Ways to Get Post Metrics

By Sarah Wong5 min read

When someone says 'I want Twitter stats via the API', they usually mean one of two things: the public counters on a tweet (likes, retweets, replies, quotes — what everyone sees on the timeline) or the private analytics counters (impressions, profile visits, link clicks — what only the tweet's author sees in their analytics dashboard). These are different categories with different auth requirements and different available paths.

This guide walks both. For public metrics: three API paths with runnable code and per-call cost. For non-public metrics: the OAuth user-context requirement that limits this surface to the tweet's author. Pricing references are URL-cited so you can verify; the multipliers are reduced from cited rates.

01 — Section

Public metrics vs non-public metrics — the split that matters

Public metrics are part of the tweet's public-facing view. Anyone can see them on the timeline; any API path that returns the tweet returns them. Fields: like_count, retweet_count, reply_count, quote_count, and (where surfaced) bookmark_count.

Non-public metrics are the analytics side: impression_count (how many timelines the tweet was shown in), url_link_clicks (how many clicked links inside), user_profile_clicks (how many clicked through to the author's profile). These are available only via the X official API with OAuth user-context auth, meaning the request runs as the account owner — you can fetch your own non-public metrics but not someone else's.

If your use case is monitoring competitors, sentiment analysis, viral-content detection, or anything tracking accounts you don't own → you're working with public metrics only. If your use case is analyzing your own account's reach → you can add non-public metrics on top via X user-context auth.

02 — Section

Path 1 — twitterapi.io batch tweet endpoint

twitterapi.io's /twitter/tweets endpoint accepts a batch of tweet IDs and returns the full tweet record for each, including public metrics. Authentication is X-API-Key. Pricing per twitterapi.io/pricing: $0.00015 per returned tweet (no developer onboarding, no monthly minimum).

Pick this when you need public metrics at scale — backfilling stats over an archive, polling a list of monitored accounts, computing engagement rates across many tweets.

python
import os, requests

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"

def tweet_stats(tweet_ids: list[str]):
    """Batch fetch — returns tweets including public_metrics."""
    r = requests.get(
        f"{BASE}/twitter/tweets",
        headers=HEADERS,
        params={"tweet_ids": ",".join(tweet_ids)},
        timeout=10,
    )
    r.raise_for_status()
    return r.json().get("tweets", [])

# Example: refresh stats for 100 tweets we're tracking
ids = ["1234567890", "2345678901", "3456789012"]
rows = tweet_stats(ids)
for t in rows:
    pm = t.get("public_metrics", {})
    print(f"  {t['id']}  likes={pm.get('like_count')}  rts={pm.get('retweet_count')}  replies={pm.get('reply_count')}")
03 — Section

Path 2 — X official public metrics via xdk / tweepy / raw requests

X's /2/tweets/{id} with tweet.fields=public_metrics returns the same public counters. Auth is a bearer token from the X Developer Console. Pricing per docs.x.com/x-api/getting-started/pricing: $0.005 per post read, deduplicated within a 24-hour UTC window.

Pick this when you're already on the X bill for write operations (post create, like, retweet, follow) and the marginal stat-read cost rides on the same auth.

python
# pip install tweepy
import tweepy

client = tweepy.Client(bearer_token="YOUR_X_BEARER")

# Single tweet
resp = client.get_tweet(id="1234567890", tweet_fields=["public_metrics"])
pm = resp.data.public_metrics
print(pm)  # {'like_count': N, 'retweet_count': N, 'reply_count': N, 'quote_count': N}

# Batch (X official allows up to 100 IDs per call)
ids = ["1234567890", "2345678901", "3456789012"]
resp = client.get_tweets(ids=ids, tweet_fields=["public_metrics"])
for t in resp.data:
    print(t.id, t.public_metrics)
04 — Section

Path 3 — non-public metrics (impressions, clicks) via X user-context

Non-public metrics require OAuth user-context auth — the request runs AS the account owner. This means:

- You can fetch impression / click counts for tweets in YOUR own authenticated account.

- You cannot fetch them for an arbitrary public tweet by some other account.

Auth flow: OAuth 2.0 with PKCE (or OAuth 1.0a if you're maintaining legacy code) → you obtain an access token bound to a specific X account → calls made with that token are scoped to that account's data. Tweepy supports this via the OAuth2UserHandler helper.

Pricing is the same per-post-read rate ($0.005) as public metrics, plus whatever overhead your auth setup incurs (which is one-time, not per-call). The constraint is access, not cost.

python
# pip install tweepy
import tweepy

# OAuth user-context — obtain an access token bound to the account whose
# non-public metrics you want to read. See docs.tweepy.org for the full
# OAuth 2.0 PKCE flow; the snippet below assumes you already have one.
client = tweepy.Client(
    consumer_key="YOUR_CONSUMER_KEY",
    consumer_secret="YOUR_CONSUMER_SECRET",
    access_token="USER_ACCESS_TOKEN",            # bound to the account owner
    access_token_secret="USER_ACCESS_TOKEN_SECRET",
)

resp = client.get_tweet(
    id="YOUR_OWN_TWEET_ID",
    tweet_fields=["non_public_metrics", "public_metrics"],
)
npm = resp.data.non_public_metrics  # impression_count, url_link_clicks, user_profile_clicks
print(npm)
05 — Section

Side-by-side comparison — 5 dimensions

Same job (fetch stats for a list of tweets) across the three paths. Numbers are derived from cited pricing pages.

Dimensiontwitterapi.ioX official (bearer)X official (user-context)
Metrics accessiblepublic (likes / RTs / replies / quotes)public (same)public + non-public (impressions / clicks)
Per-call cost$0.00015 / tweet returned$0.005 / post read$0.005 / post read
Auth surfaceX-API-Key headerbearer token from X Developer ConsoleOAuth 2.0 PKCE or OAuth 1.0a, user-bound
Account scopeany public tweetany public tweetauthor-only
Best forbulk public-stats refresh at low costmixed read+write under X authown-account analytics

Two practical patterns: (a) for monitoring or competitive analysis (you don't own the accounts), the choice is between paths 1 and 2 — cost ratio is 33.33× per call at the cited rates; (b) for your own account analytics, you need path 3 — non-public metrics are not available via twitterapi.io because the auth model is fundamentally different (no user-context flow).

06 — Section

Batch patterns — fetching many tweets' stats efficiently

Batch IDs per call: both twitterapi.io and X official support multiple IDs per call. Use larger batches (up to the documented per-call limit) to reduce HTTP overhead.

Refresh cadence: tweet stats (likes, RTs) change rapidly in the first ~24h then settle. A reasonable cadence is poll every 5-15 minutes for fresh content, hourly for content 24-72h old, daily for older. Calibrate against your own retention needs.

Storage: persist the stat snapshots so you can compute velocity (delta per unit time) — that's the operationally interesting signal for content monitoring. A simple (tweet_id, captured_at, like_count, retweet_count, ...) row layout works.

Rate handling: 429s happen. Wrap with retry-on-429 + jittered backoff. Treat 5xx the same way.

07 — Section

Picking a path — the decision rule

Need stats for tweets you don't own at scale? → twitterapi.io path 1. Public metrics are available, no OAuth user-context, per-call cost ratio works against you on volume otherwise.

Already paying X for credits (you write posts, you read profiles)? → use X official bearer-token path 2 for marginal stat reads. Auth is unified.

Need your own account's non-public metrics (impressions, clicks)? → X official path 3 with OAuth user-context. This is the only path; twitterapi.io and X bearer-only can't see non-public.

Most analytics pipelines split: path 1 for the broad public-stats monitoring workload, path 3 for the deeper own-account analytics. They answer different questions.

python
# Practical example: track engagement velocity across N tweets, refresh hourly,
# compute delta-per-hour as the signal.
import os, requests, time
from datetime import datetime, timezone

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"

def batch_stats(ids: list[str]):
    r = requests.get(
        f"{BASE}/twitter/tweets",
        headers=HEADERS,
        params={"tweet_ids": ",".join(ids)},
        timeout=10,
    )
    r.raise_for_status()
    return r.json().get("tweets", [])

def snapshot(ids: list[str]):
    now = datetime.now(timezone.utc).isoformat()
    out = []
    for t in batch_stats(ids):
        pm = t.get("public_metrics", {})
        out.append({
            "tweet_id": t["id"],
            "captured_at": now,
            "like_count": pm.get("like_count"),
            "retweet_count": pm.get("retweet_count"),
            "reply_count": pm.get("reply_count"),
            "quote_count": pm.get("quote_count"),
        })
    return out

# Persist each snapshot row, compute delta per cadence downstream.
# Cost framing (math from cited pricing):
#   100 tweets × 24 hourly snapshots × $0.00015 = $0.36 per day at twitterapi.io rates;
#   same workload at X official: 100 × 24 × $0.005 = $12 per day. Multiply by tracked count.
08 — Questions

Questions readers ask

Why are impressions not available via twitterapi.io?

Impressions are a non-public metric — they require OAuth user-context auth on X official, which scopes the request to a specific account owner. twitterapi.io operates on API-key auth without per-account OAuth, so the data simply isn't accessible through that surface. For impressions you must use X official user-context.

How fresh are public_metrics — is there a delay?

Public metrics update in near-real-time on X and propagate to read APIs quickly. Both twitterapi.io and X official return counts that reflect very recent state. For sub-minute precision validate against the live UI for your specific tweet — exact propagation latency can vary.

Is `bookmark_count` available?

Bookmark counts have been on/off in public surfaces over time. Check the field set returned by /twitter/tweets and the tweet.fields documentation at docs.x.com for the current availability before relying on it.

Can I get historical stats for an old tweet?

You can read CURRENT stats for any reachable tweet — old tweets returned by either path include their current public_metrics. There is no time-series of past stats available via the API — for that you must capture snapshots yourself and store the deltas.

How does cost scale if I need to refresh 10,000 tweets per hour?

Math from the cited pricing pages. twitterapi.io: 10,000 × $0.00015 = $1.50 per refresh, ~$36/day at hourly cadence. X official: 10,000 × $0.005 = $50 per refresh, ~$1,200/day. 24h dedup window on X reduces costs if you re-poll the same IDs same UTC day — but the per-fresh-poll cost is the relevant metric.

Do I need a verified X Developer account to use the official path?

You need a developer account to get the bearer token, yes. The application flow is at developer.x.com. twitterapi.io's signup path is shorter — sign up at twitterapi.io, get an API key, no developer review. If onboarding friction is a factor, that's a tie-breaker.

09 — Further reading

Continue

Sources & further reading
More from this series
Build it

Stop reading. Start building.

Starter credits cover real testing on real data. Google sign-in, no card, no application queue.

Get an API key
    Twitter (X) Stats API — Public/Private | TwitterAPI.io