Twitter (X) Viewer API — A Developer's Read-Only Guide
A 'Twitter viewer' workflow — read what's on a public X profile without authenticating as the account owner — is a foundational dev task: research dashboards, public-profile lookup tools, OSINT-style monitoring, brand-mention surface. The data is public; you just need an API path that doesn't require logging in as the target account.
This guide walks the read-only viewer pattern with runnable Python: fetch profile, fetch recent tweets, render or persist the data. Per-call cost from each provider's published pricing page; you can re-derive the multipliers from the cited rates.
What 'viewer' means in this context
A viewer reads public profile + tweet data — the same surface anyone with a browser can see at x.com/. No write access, no OAuth user-context, no special permissions beyond API-key auth.
Common viewer use cases:
- Public profile lookup — render a profile card on your site without iframe-embedding x.com
- Recent-tweet feed — show an account's last N posts in your own UI
- OSINT and research — automated monitoring of public accounts for journalism or academic research
- Aggregation dashboards — fetch many profiles for analytics tools, ranking boards, leaderboard sites
Path 1 — twitterapi.io viewer endpoints
twitterapi.io's /twitter/user/info returns profile data; /twitter/user/last_tweets returns recent tweet timeline. Auth is X-API-Key header — no X Developer account, no OAuth flow.
Pricing per twitterapi.io/pricing: $0.00018 per profile, $0.00015 per tweet.
import os, requests
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
def view_profile(username: str) -> dict:
"""GET /twitter/user/info — profile read."""
r = requests.get(
f"{BASE}/twitter/user/info",
headers=HEADERS,
params={"userName": username},
timeout=10,
)
r.raise_for_status()
return r.json()
def view_tweets(username: str) -> list:
"""GET /twitter/user/last_tweets — recent timeline."""
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", [])
profile = view_profile("twitterapi_io")
print(f"@{profile.get('userName')}: {profile.get('followers_count')} followers")
for t in view_tweets("twitterapi_io")[:5]:
pm = t.get("public_metrics", {})
print(f" {t['id']}: {t.get('text', '')[:80]} (likes={pm.get('like_count')})")
Path 2 — X official viewer endpoints
X's official path: /2/users/by/username for profiles, /2/users/{id}/tweets for the timeline. Both require a bearer token from the X Developer Console — onboarding adds friction.
Pricing per docs.x.com/x-api/getting-started/pricing: $0.010 per profile, $0.005 per post read. 24-hour UTC dedup window applies.
# pip install tweepy
import tweepy
client = tweepy.Client(bearer_token="YOUR_X_BEARER")
user = client.get_user(username="twitterapi_io", user_fields=["public_metrics", "description"])
print(f"@{user.data.username}: {user.data.public_metrics['followers_count']} followers")
resp = client.get_users_tweets(
id=user.data.id,
max_results=5,
tweet_fields=["public_metrics"],
)
for t in resp.data or []:
print(f" {t.id}: {t.text[:80]}")
Side-by-side comparison — 2 viewer paths
Same job (view a public profile + recent tweets) framed across two paths. Costs derived from cited pricing.
Two practical patterns: (a) per-call cost ratio is ~55× per profile and ~33× per tweet; (b) onboarding friction differs — twitterapi.io's signup is a few minutes, X Developer review can take days.
Building a viewer UI — practical pattern
Card layout: render profile fields (avatar, display name, handle, bio, follower count, verified badge) in a card component. Below it, render the recent-tweet timeline with public_metrics per tweet.
Caching: avoid re-hitting the API on every page render. Cache profiles 15-60 minutes, tweets 5 minutes. Persist client-side or in your CDN edge.
Pagination: if you need to view beyond the recent-tweets default, follow next_cursor for older posts. Most viewer products show ~20-50 recent tweets and link out for the full archive.
Privacy + ToS: viewer products that bulk-aggregate user data should comply with X's developer terms and your jurisdiction's privacy laws. Use rate limits and respectful caching to avoid scrape-like patterns.
Cost framing — 10K profile views per day
Math from cited pricing pages:
- 10,000 profile lookups via twitterapi.io: $1.80/day = ~$54/mo
- Same workload via X official: $100/day = ~$3,000/mo
- Including 5 recent tweets per profile: +$0.0075 (twitterapi.io) or +$0.25 (X official) per lookup
- At this scale: ~$2.55/day twitterapi.io vs ~$350/day X official
For viewer-product scale (multi-thousand daily lookups), the cost differential makes twitterapi.io the only path that doesn't dominate your operating costs.
Picking a path — the decision rule
Building a public viewer product (website, dashboard, OSINT tool)? → twitterapi.io. Cost compounds favorably; onboarding is minutes.
Already on the X bill for other workflows? → X official; marginal viewer-cost rides on same auth.
One-off viewer for research? → either works at single-call cost. Pick by which auth is faster.
Most production viewer products run twitterapi.io for the read layer + cache results aggressively to amortize calls across many users.
# Practical example: build a public-profile viewer endpoint.
# Caches results 5 min in-process; production should use Redis or CDN edge cache.
import os, requests, time
from functools import lru_cache
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
CACHE_TTL = 300 # 5 min
_cache = {}
def get_view(username: str) -> dict:
now = time.time()
if username in _cache:
cached_at, data = _cache[username]
if now - cached_at < CACHE_TTL:
return data
profile = requests.get(
f"{BASE}/twitter/user/info",
headers=HEADERS, params={"userName": username}, timeout=10,
).json()
tweets = requests.get(
f"{BASE}/twitter/user/last_tweets",
headers=HEADERS, params={"userName": username}, timeout=10,
).json().get("data", [])
view = {"profile": profile, "tweets": tweets[:20]}
_cache[username] = (now, view)
return view
view = get_view("twitterapi_io")
print(f"@{view['profile'].get('userName')}: {view['profile'].get('followers_count')} followers")
for t in view["tweets"][:3]:
print(f" {t['id']}: {t.get('text', '')[:80]}")
# Cost framing (math from cited pricing pages):
# 1 profile + 20 tweets per view = $0.00018 + 20 * $0.00015 = $0.00318
# 1,000 views/day uncached: $3.18/day = ~$95/mo at twitterapi.io rates
# With 5-min cache and even traffic, real call count drops 80-95% — bill drops accordinglyQuestions readers ask
Do I need to log in to view a public X profile via API?
No — public profile + tweet data is read without auth-as-the-account-owner. You need API auth (key or bearer token), but not OAuth user-context. Anyone calling the read API sees the same public data.
Can I view protected / private accounts?
No. Private accounts return restricted data — profile basics may be visible but tweets are not. This is by design; X enforces the privacy at the platform layer.
Will the viewed account know I'm viewing them?
API reads do not surface to the target account as 'visits' or notifications. The platform doesn't expose viewer-identity for read API calls.
How fresh is the data?
Near-real-time on both twitterapi.io and X official. Both APIs return current state at call time — for sub-second precision validate against the live x.com UI for your specific account.
Can I cache responses to reduce API cost?
Yes, and you should. Most viewer products cache profile data 15-60 minutes and tweet data 5 minutes. For high-traffic viewer products this drops 80-95% of API calls. Use Redis, your CDN edge, or simple in-process caching.
Is there a limit on how many profiles I can view per day?
twitterapi.io: no monthly minimum or cap — pay per call. X official: rate limits documented per endpoint at docs.x.com. For viewer products, the binding constraint is usually budget, not rate limit.
Continue
- Twitter (X) API — cluster hub
- Twitter (X) API in Python — complete guide
- Twitter (X) profile analytics API guide
- Twitter (X) counter API guide
- 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