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

Blogtwitter viewer

Twitter (X) Viewer API — A Developer's Read-Only Guide

By Sarah Wong4 min read

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.

01 — Section

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

02 — Section

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.

python
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')})")
03 — Section

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.

python
# 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]}")
04 — Section

Side-by-side comparison — 2 viewer paths

Same job (view a public profile + recent tweets) framed across two paths. Costs derived from cited pricing.

Dimensiontwitterapi.ioX official
AuthX-API-Key, sign-up onlybearer token, X Developer review
Profile cost$0.00018$0.010
Tweet cost$0.00015$0.005
Librarynonexdk or tweepy
24h UTC dedupnoyes
Best forviewer products, OSINT, aggregationalready-on-X-bill mixed workloads

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.

05 — Section

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.

06 — Section

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.

07 — Section

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.

python
# 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 accordingly
08 — Questions

Questions 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.

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) Viewer API — Read-Only | TwitterAPI.io