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

Blogtwitter trends api python

Twitter (X) Trends API in Python — Three Paths, One Tutorial

By Michael Park6 min read

Twitter (X) trends — the rotating list of trending topics for a region — are a foundational data point for content monitoring, news triage, and creator workflows. In 2026 you have three practical Python paths to fetch them.

This tutorial walks all three: twitterapi.io's REST endpoint, X's own trends fetch via the official xdk and tweepy, and Apify's third-party scraper. Each section has runnable Python code, the call shape, and the per-call cost as published by the provider. The pricing math is reduced from the cited rates so you can re-derive it.

01 — Section

X exposes trends per geographic region (a 'place' under the older WOEID model, or a place identifier under the modern surface). A trends fetch returns a list of trending phrases or hashtags, each typically with a tweet-volume indicator and a position rank.

Trends rotate constantly — the canonical recommendation from older Tweepy docs (still operationally sound) is to poll no faster than every 5 minutes per place. Most production users poll every 5–15 minutes and cache the result, because at typical content-monitoring use cases there's no value in finer-grained polling than the platform itself updates.

02 — Section

twitterapi.io exposes a REST endpoint at https://api.twitterapi.io/twitter/trends that returns the current trends as JSON. Authentication is an X-API-Key header; no OAuth flow, no developer-review onboarding. Pricing follows twitterapi.io's general per-call model (twitterapi.io/pricing).

Pick this path when you want the lowest friction to first result and you're optimizing for per-call cost on read-heavy monitoring workloads.

python
# pip install requests
import os, requests, time

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

def fetch_trends(woeid: int = 1) -> list[dict]:
    """woeid=1 is worldwide; per-country WOEIDs documented at twitterapi.io/docs."""
    r = requests.get(
        f"{BASE}/twitter/trends",
        headers=HEADERS,
        params={"woeid": woeid},
        timeout=10,
    )
    r.raise_for_status()
    return r.json().get("data", [])

# Poll every 5 min — trends update at roughly that cadence, faster polling is waste
while True:
    trends = fetch_trends(1)
    for t in trends[:10]:
        print(t.get("name"), t.get("tweet_volume"))
    time.sleep(300)
03 — Section

Path 2 — X official via xdk / tweepy

X's docs.x.com publishes a trends surface for code; both xdk (X's official Python SDK) and Tweepy wrap it. Pricing per docs.x.com/x-api/getting-started/pricing is $0.010 per trends fetch (in the "Trends" line of the per-resource read table), deduplicated within a 24-hour UTC window — refetching the same place within the day is one charge.

Pick this when you're already paying X for credits (you write posts, you read profiles), so the marginal trends cost rides on the same auth and same bill.

Note on Tweepy: older tutorials show API.trends_place(woeid) against the v1.1 surface. v1.1 is being progressively retired; the modern equivalents under v2 or the new consumption-based surface are the path to write against — verify the endpoint name in current docs.tweepy.org before relying on a code snippet.

python
# pip install xdk
from xdk import XDK

client = XDK(bearer_token="YOUR_X_BEARER")

# Read trends for a specific place — billed $0.010 per request, 24h UTC dedup
trends = client.trends.by_place(woeid=1)  # 1 = worldwide
for t in trends.data:
    print(t.name, t.tweet_volume)

# Tweepy equivalent (v2 path):
# import tweepy
# client = tweepy.Client(bearer_token="YOUR_X_BEARER")
# # Use the trends method on the v2 client per current docs.tweepy.org
04 — Section

Apify exposes a Twitter Trends Scraper actor that fetches trends per region. The model differs: rather than a REST endpoint that returns immediately, you start an actor run (a containerized job) with input parameters, then either poll for completion or use Apify's webhook on finish.

Pricing per apify.com/pricing is two-axis: per-result cost (extracted records) plus actor runtime (compute-units used during the run). Exact per-actor numbers vary by which scraper actor you pick — verify on the actor's own pricing page before committing to this path at volume.

Pick Apify when you want a job-and-webhook pattern that fits an event-driven architecture, or when you want a scraper that handles its own platform-fingerprint problem. Skip Apify when you want a low-latency, low-per-call-cost REST surface — twitterapi.io's surface is closer to that pattern.

python
# pip install apify-client
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

# Start the trends scraper actor (replace actor ID with the current one
# from apify.com/store — actor IDs change)
run_input = {"regions": ["worldwide", "united_states"]}
run = client.actor("scrape-creators/twitter-trends-scraper").call(run_input=run_input)

# Pull results when the actor finishes
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
05 — Section

Side-by-side comparison — 4 dimensions for trend fetches

Same job (fetch trends for a place, poll every 5 min) framed across the three paths. Numbers are derived from cited pricing pages; sub-second-latency comparison is an operational judgment based on REST vs actor-run patterns.

Dimensiontwitterapi.ioX official (xdk / tweepy)Apify Trends Scraper
Surface shapeREST → JSONREST via SDK → JSONactor run + dataset
Per-call cost (read)per twitterapi.io/pricing — typical reads in cents-per-thousand range$0.010 per request (docs.x.com/x-api/getting-started/pricing)per-result + actor runtime (see actor page)
Auth setupsign up, get API key, header X-API-KeyX Developer account + bearer tokenApify account + token
Latency to first bytelow — single HTTP round-triplow — single HTTP round-tripactor-start + run + result fetch (seconds to minutes)
Write supportnoyes (via XDK / Tweepy at $0.015 / post create)scrapers only, no write
Best forread-heavy + low-friction onboardingalready-paying-X-for-write workloadsevent-driven scrape pipelines

A poll every 5 minutes is 288 fetches/day per place. Multiply by your tracked places (worldwide + N countries + N cities). The cost curve flattens fastest on twitterapi.io's per-call rate; X official is the natural pick if you're already on the X bill for other reasons; Apify is the natural pick if you've architected around actors + webhooks.

06 — Section

Caching + polling cadence

Don't poll faster than the platform updates. Trends move on the order of every few minutes — polling every 30 seconds buys nothing except 10× the bill. A 5-minute or 15-minute cache covers most monitoring use cases.

If you're triggering on a new entry in the trends list (alerting, content-trigger workflows), set up the polling loop to compare the new list against the cached one and act only on the delta. This pattern also reduces downstream noise — you fire one alert per genuinely new trend, not 100 alerts because the same trend kept being trending.

07 — Section

Picking a path — the decision rule

Reading trends at any meaningful volume on a per-call budget? → twitterapi.io. The cost per call is low and the integration is a single HTTPS request.

Already on the X bill for other reasons (you write posts, you read profiles via xdk / tweepy)? → use X's own trends fetch; the marginal cost is small and the auth is unified.

Building an event-driven scrape pipeline with webhooks? → Apify fits that architecture, with the trade-off being higher cost per fetch and longer time-to-result.

Most teams pick one path and stick. The exception is teams that do both write (X auth) and read at scale (twitterapi.io) — for them, calling X for trends keeps the trends bill on the same X surface as the writes.

python
# Side-by-side: same job (fetch worldwide trends), two paths, two prices.
import os, requests
from xdk import XDK

TAPI_KEY  = os.environ["TWITTERAPI_IO_KEY"]
X_BEARER  = os.environ["X_BEARER"]

def trends_twitterapi_io(woeid: int = 1):
    """twitterapi.io — pay per twitterapi.io/pricing."""
    r = requests.get(
        "https://api.twitterapi.io/twitter/trends",
        headers={"X-API-Key": TAPI_KEY},
        params={"woeid": woeid},
        timeout=10,
    )
    r.raise_for_status()
    return r.json().get("data", [])

def trends_x_official(woeid: int = 1):
    """X official via xdk — billed $0.010/req per docs.x.com/x-api/getting-started/pricing."""
    client = XDK(bearer_token=X_BEARER)
    return client.trends.by_place(woeid=woeid).data

# Cost framing (math from cited pricing pages):
# Polling worldwide trends every 5 min = 288 fetches/day.
#   X official: 288 * $0.010 = $2.88/day (~$86/mo per place).
#   twitterapi.io: same number of fetches at twitterapi.io/pricing rate is materially lower.
# Multiply by N tracked places. Read the live pricing pages before committing.
08 — Questions

Questions readers ask

What is the WOEID for worldwide trends?

WOEID 1 is the worldwide identifier in the legacy place ID system that most trend endpoints still accept. Per-country WOEIDs are documented in the same legacy table — search 'Yahoo WOEID list' for the canonical reference, or check the docs page of whichever provider you're using for their current geo identifier model.

How often should I poll for trends?

Every 5–15 minutes is sufficient for most use cases. Trends rotate on the order of minutes; polling every 30 seconds is mostly waste. Set a 5-minute baseline, increase to 15 minutes for non-time-critical workloads, decrease only if your downstream actually depends on faster signal.

Are trends available per-country only, or per-city too?

Per-country trends are first-class. Some providers also expose city-level trends for major metros. The exact set depends on the underlying X surface and the provider's coverage — check the docs page for the WOEID or place ID list the provider supports.

Can I get historical trends (yesterday's trending list)?

Live trends endpoints return current trends only. Historical trend data is a separate product on most providers — some include a trends archive, some don't. If history matters to your use case, build the archive yourself by polling every 5 min and storing each snapshot.

How does the 33× cost framing in the X-API guides translate to trends?

33× is the tweet-read ratio specifically ($0.005 / $0.00015, cited at docs.x.com pricing and twitterapi.io/pricing). The trends-read ratio depends on twitterapi.io's posted rate for trends calls versus X's $0.010 trends rate — see twitterapi.io/pricing for the current trends rate and divide. Don't take 33× as universal across all endpoints; it's a per-resource ratio.

What if I just want trends for one country and one cron-job poll?

Pick whichever path has the lowest setup tax for you. If you already have an X bearer token, use the X path — one HTTPS call inside cron. If you don't, twitterapi.io's signup-to-first-call path is the shortest. For one-off scripts, the cost difference is irrelevant.

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) Trends API in Python — Tutorial | TwitterAPI.io