PythonTwitter APIX APITutorialtweepysnscrape

How to Use the Twitter API with Python, 2026 Tutorial

Step-by-step Python tutorial for the Twitter API in 2026. Working code for search, users, DMs, pagination, retries, plus a tweepy migration guide.

GetXAPI·
Python Twitter API tutorial, full working code samples for 2026

Most "how to use the Twitter API in Python" guides are stuck in 2022, they tell you to install tweepy, set up four OAuth credentials, and pretend the free tier still exists. That advice is broken in 2026. The free tier was removed in February 2023, the pay-per-use model that replaced it makes every request cost money, and tweepy carries the full weight of the official X API's quirks.

This tutorial shows you the version that actually works in 2026: a Python integration with the Twitter / X API that ships in 30 seconds, has no developer-account approval queue, costs $0.05 per 1,000 tweets, and works with a single requests import. Every section has runnable code. Every endpoint is real. By the end you'll have a working Python client for search, user lookups, followers, tweet creation, DMs, and pagination.

TL;DR: The fastest Python integration is pip install requests, sign up at getxapi.com, grab your API key, and run the snippet below. The rest of this guide expands on every common use case.

import requests

API_KEY = "YOUR_API_KEY"  # get one in 30 seconds at getxapi.com/signup

resp = requests.get(
    "https://api.getxapi.com/twitter/user/info",
    params={"userName": "elonmusk"},
    headers={"Authorization": f"Bearer {API_KEY}"},
)
user = resp.json()["data"]
print(user["name"], ",", user["followers"], "followers")

Run that with a real key and you get back a JSON profile with name, followers, bio, verification status, and 30+ other fields. Total setup time: under a minute.

Three Python Paths to Twitter Data in 2026

In 2026, three approaches cover 95% of Python Twitter integrations: the GetXAPI REST endpoint via requests at $0.001 per call, the official X API via tweepy at $0.005 per post read, and snscrape which is mostly broken and not recommended for production. The right choice depends on whether you need OAuth user-delegated flows (only tweepy handles those) or data collection (GetXAPI is 100x cheaper).

Most Python developers reach the Twitter API through one of three libraries. Each has a different cost, complexity, and reliability profile.

Path What it is Cost in 2026 Setup time When to pick it
GetXAPI + requests Third-party REST API. Single Bearer header. $0.05 per 1,000 tweets ($0.001 per call). $0.10 free at signup. < 5 minutes Most data-collection workloads, research, analytics, monitoring, bots, dashboards.
tweepy + Official X API Official Python library wrapping the X API v2. OAuth 2.0 / Bearer token. $0.005 per post read, $0.010 per user lookup, $0.015 per write. ~$5-$10 per 1,000 tweets. Hours to days (developer-account approval) Only when you need OAuth user-delegated flows (apps where end users log in with their X account).
snscrape Open-source scraping library. No auth required. $0, but increasingly broken. < 5 minutes (until it breaks) Almost never in 2026. The maintainers paused active development in 2023; most endpoints are unreliable or fully broken after X tightened scraping defenses.

Most Python tutorials still default to tweepy. That's a 2022-shaped recommendation. In 2026, tweepy means paying official X API rates (100x more per tweet) for an integration that takes a developer-account application, OAuth setup, and rate-limit retry logic on top. For everything except OAuth-login apps, GetXAPI is faster, cheaper, and simpler.

Quick Start: GetXAPI + Python in 5 Minutes

Getting a working Twitter API call in Python takes four steps: install requests, sign up at getxapi.com for a Bearer key (no developer account approval required), set the key as an environment variable, and call the endpoint. The whole setup is under five minutes.

Step 1, Install requests

pip install requests

That's the entire dependency. No SDK, no compiled extensions. If you're using httpx or aiohttp already, those work too, the API is plain JSON over HTTPS.

Step 2, Get your API key

Sign up at getxapi.com/signup with Google or email. The dashboard generates your unique Bearer key immediately, no developer-account application, no approval queue, no credit card. Every new account gets $0.10 in free credits, which covers about 100 API calls (~2,000 tweets), enough to validate every endpoint before you commit.

For the deeper context on what an "X API key" actually is and the four credential types in the official ecosystem, see What is a Twitter API key?.

Step 3, Make your first call

import os
import requests

API_KEY = os.environ["GETXAPI_KEY"]  # never hardcode keys

def get_user(username: str) -> dict:
    resp = requests.get(
        "https://api.getxapi.com/twitter/user/info",
        params={"userName": username},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json()["data"]

user = get_user("elonmusk")
print(f"{user['name']} (@{user['userName']})")
print(f"  Followers:  {user['followers']:,}")
print(f"  Following:  {user['following']:,}")
print(f"  Verified:   {user.get('isVerified', False)}")

Save your key as an environment variable (export GETXAPI_KEY=...) and run the script. Successful response includes the user's full profile with all fields populated by default, no field-expansion gymnastics like the official X API v2 requires.

Eight Common Python Use Cases (with Working Code)

This section covers the eight things most Python developers actually want to do with Twitter data. Every snippet is runnable, copy it into a file, swap the API key, and execute.

1. Search Recent Tweets

def search_tweets(query: str, max_results: int = 20) -> list[dict]:
    resp = requests.get(
        "https://api.getxapi.com/twitter/tweet/advanced_search",
        params={"q": query, "product": "Latest"},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json().get("tweets", [])[:max_results]

tweets = search_tweets("from:elonmusk filter:replies")
for t in tweets:
    print(f"[{t['createdAt']}] {t['text'][:140]}")

The q parameter accepts the full Twitter search-operator syntax: from:, to:, since:, until:, min_faves:, min_retweets:, lang:, filter:, etc. For the complete operator reference, see the Twitter advanced search operators guide.

2. User Profile Lookup

def get_user_info(username: str) -> dict:
    resp = requests.get(
        "https://api.getxapi.com/twitter/user/info",
        params={"userName": username},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json()["data"]

profile = get_user_info("naval")
print(profile["name"], ",", profile["followers"], "followers")
print("Bio:", profile["description"])
print("Joined:", profile["createdAt"])

Returns the full profile object: name, username, description, follower / following counts, verification status, profile images, account creation date, and pinned tweet ID.

3. Get a User's Recent Tweets

def get_user_tweets(username: str) -> list[dict]:
    resp = requests.get(
        "https://api.getxapi.com/twitter/user/tweets",
        params={"userName": username},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json().get("tweets", [])

for t in get_user_tweets("paulg")[:5]:
    print(f"♥ {t['likeCount']:>6}{t['retweetCount']:>5}  {t['text'][:80]}")

Each tweet object has the full author data inline, no field-expansion needed. Sort by engagement, filter by date, or pipe straight into your dashboard.

4. Get Followers

def get_followers(username: str, limit: int = 200) -> list[dict]:
    resp = requests.get(
        "https://api.getxapi.com/twitter/user/followers",
        params={"userName": username},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json().get("followers", [])[:limit]

followers = get_followers("elonmusk")
print(f"Got {len(followers)} followers")
verified = [f for f in followers if f.get("isVerified")]
print(f"  ↪ {len(verified)} verified")

For verified-only followers without filtering client-side, use the verified_followers endpoint instead, it returns a curated list and skips the rest of the noise.

5. Get Replies to a Tweet

def get_tweet_replies(tweet_id: str) -> list[dict]:
    resp = requests.get(
        "https://api.getxapi.com/twitter/tweet/replies",
        params={"tweetId": tweet_id},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json().get("replies", [])

replies = get_tweet_replies("1234567890")
for r in replies[:10]:
    print(f"@{r['author']['userName']}: {r['text'][:100]}")

This is one of the endpoints the official X API makes painfully expensive, at $0.005 per resource, fetching 100 replies on the official API costs $0.50. On GetXAPI it's a single $0.001 call.

6. Advanced Search with Date Ranges

from datetime import date

def date_range_search(query: str, start: date, end: date) -> list[dict]:
    full_query = f"{query} since:{start.isoformat()} until:{end.isoformat()}"
    resp = requests.get(
        "https://api.getxapi.com/twitter/tweet/advanced_search",
        params={"q": full_query, "product": "Latest"},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json().get("tweets", [])

results = date_range_search(
    "openai",
    start=date(2026, 4, 1),
    end=date(2026, 5, 1),
)
print(f"April 2026, {len(results)} tweets matching 'openai'")

The since: / until: operators take YYYY-MM-DD dates. For deep historical sweeps that go beyond the rolling 7-day window, chunk your query by date range and stitch the results together, the Twitter advanced search operators guide covers the chunking pattern.

7. Send a Tweet (Write Action)

def send_tweet(text: str, login_cookies: str) -> dict:
    resp = requests.post(
        "https://api.getxapi.com/twitter/tweet/create",
        json={"text": text, "loginCookies": login_cookies},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json()

result = send_tweet(
    text="Posting from Python via GetXAPI 🐍",
    login_cookies=os.environ["TWITTER_LOGIN_COOKIES"],
)
print("Tweet ID:", result.get("tweet_id"))

Write actions (tweet/create, tweet/favorite, tweet/retweet, dm/send) take your X login cookies as a parameter, they're used in-flight to authorize the action and are never stored. For the full DM workflow, see Sending Twitter DMs via API.

8. Send a Direct Message

def send_dm(recipient_username: str, message: str, login_cookies: str) -> dict:
    resp = requests.post(
        "https://api.getxapi.com/twitter/dm/send",
        json={
            "userName": recipient_username,
            "text": message,
            "loginCookies": login_cookies,
        },
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json()

send_dm(
    recipient_username="bozad",
    message="Hello from Python",
    login_cookies=os.environ["TWITTER_LOGIN_COOKIES"],
)

DM endpoints cost $0.002 per call. The recipient must accept DMs from non-followers, or you must already be following each other, no API can override that platform-level setting.

Pagination in Python

GetXAPI uses cursor-based pagination: each response includes a next_cursor string and a has_more boolean. Pass next_cursor back as the cursor parameter on the next request and stop when has_more is false. This works the same way across search, followers, and replies endpoints.

Most Twitter API endpoints return paginated results. GetXAPI uses cursor-based pagination, every response includes next_cursor and has_more flags so you can stream through pages cleanly.

def paginate(url: str, params: dict, max_pages: int = 10) -> list[dict]:
    all_items = []
    cursor = None

    for _ in range(max_pages):
        if cursor:
            params["cursor"] = cursor
        resp = requests.get(
            url,
            params=params,
            headers={"Authorization": f"Bearer {API_KEY}"},
        )
        resp.raise_for_status()
        data = resp.json()

        items = data.get("tweets") or data.get("followers") or data.get("replies") or []
        all_items.extend(items)

        if not data.get("has_more"):
            break
        cursor = data.get("next_cursor")

    return all_items

# Example: get up to 200 tweets matching a query
results = paginate(
    "https://api.getxapi.com/twitter/tweet/advanced_search",
    params={"q": "from:elonmusk", "product": "Latest"},
    max_pages=10,
)
print(f"Fetched {len(results)} tweets across paginated calls")

Compare with tweepy.Paginator against the official X API: same pattern, but the tweepy version needs tweet_fields=, expansions=, user_fields=, and you pay $0.005 per result instead of $0.001 per call.

Start building with GetXAPI

$0.05 per 1,000 tweets. $0.10 free credits. No credit card required.

Error Handling and Retries in Python

Production Twitter API code needs to handle three transient failure cases: 429 rate-limit responses (rare on GetXAPI but possible), 5xx server errors from upstream X outages, and network-level timeouts from hung connections. The pattern is exponential backoff with a ceiling, retrying only on 429 and 5xx, and raising immediately on 4xx.

Production code should handle transient failures gracefully. Even on a no-rate-limit API like GetXAPI, network errors and upstream X outages still happen.

import time
import requests
from requests.exceptions import RequestException

def fetch_with_retry(url: str, params: dict, max_retries: int = 3) -> dict:
    headers = {"Authorization": f"Bearer {API_KEY}"}
    delay = 1.0

    for attempt in range(max_retries):
        try:
            resp = requests.get(url, params=params, headers=headers, timeout=15)
            if resp.status_code == 429:
                # Rare on GetXAPI, but handle it for defensive correctness
                wait = float(resp.headers.get("Retry-After", delay))
                time.sleep(wait)
                continue
            if resp.status_code >= 500:
                time.sleep(delay)
                delay *= 2
                continue
            resp.raise_for_status()
            return resp.json()
        except RequestException as exc:
            if attempt == max_retries - 1:
                raise
            time.sleep(delay)
            delay *= 2

    raise RuntimeError("Exhausted retries")

For more elegant retry logic, the tenacity library is excellent, wrap any function with @retry(stop=stop_after_attempt(3), wait=wait_exponential()) and you get exponential backoff for free.

Rate Limits, What You Actually Have to Handle

The official X API enforces per-endpoint 15-minute windows plus some 24-hour daily caps, returning 429 with x-rate-limit-reset headers when you hit them. GetXAPI has a 50-call-per-15-minute limit on advanced_search but no platform-level rate caps on most endpoints, so production Python code is dramatically simpler: no per-endpoint queues, no reset-time parsing, no semaphores.

This is where Python integrations that target the official X API get painful, and where GetXAPI's design pays off.

Official X API: every endpoint has a 15-minute rate-limit window (and some have additional 24-hour daily caps). Hitting a limit returns 429 Too Many Requests with x-rate-limit-reset headers. Production tweepy code needs per-endpoint queues, exponential backoff, and reset-time parsing, typically 100-200 lines of scaffolding before your first business-logic line.

GetXAPI: no platform-level rate limits. The same Python loop that hits the API once works for 10,000 calls. You don't need queues, backoff, or reset-time parsing for normal-volume workloads, the simple loop is enough.

For the full per-endpoint rate-limit comparison and the headers you need to read on the official API, see the Twitter API rate limits comparison.

Async Python with httpx (Advanced)

httpx.AsyncClient with asyncio.gather lets you fan out multiple GetXAPI calls concurrently without coordinating around rate-limit windows. A five-account profile fetch that takes five serial seconds runs in under two seconds in parallel, and the pattern scales to dozens of concurrent requests with no extra semaphore logic.

For high-throughput scrapers and concurrent fetches, drop in httpx.AsyncClient and run requests in parallel.

import asyncio
import httpx

API_KEY = os.environ["GETXAPI_KEY"]

async def fetch_user(client: httpx.AsyncClient, username: str) -> dict:
    resp = await client.get(
        "https://api.getxapi.com/twitter/user/info",
        params={"userName": username},
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    resp.raise_for_status()
    return resp.json()["data"]

async def fetch_many(usernames: list[str]) -> list[dict]:
    async with httpx.AsyncClient(timeout=15) as client:
        tasks = [fetch_user(client, u) for u in usernames]
        return await asyncio.gather(*tasks)

usernames = ["elonmusk", "naval", "paulg", "patio11", "sama"]
profiles = asyncio.run(fetch_many(usernames))
for p in profiles:
    print(p["name"], ",", p["followers"], "followers")

asyncio.gather runs all five lookups concurrently. On GetXAPI this is fine because there's no platform-level rate limit to coordinate around. On the official X API you'd need a semaphore plus per-endpoint window tracking to avoid burst-throttling.

Migrating from tweepy to GetXAPI

If you have a tweepy codebase and want to move to GetXAPI, the translation is direct. The two libraries cover the same surface area; only the auth model and method names change.

tweepy method (Official X API) GetXAPI equivalent
client.get_user(username="...") GET /twitter/user/info?userName=...
client.get_users_tweets(user_id, max_results=...) GET /twitter/user/tweets?userName=...
client.search_recent_tweets(query=...) GET /twitter/tweet/advanced_search?q=...
client.get_users_followers(user_id) GET /twitter/user/followers?userName=...
client.get_tweet(tweet_id) GET /twitter/tweet/detail?tweetId=...
client.create_tweet(text=...) POST /twitter/tweet/create
client.create_direct_message(...) POST /twitter/dm/send

A side-by-side example, fetching a user's last 20 tweets:

# Before: tweepy + Official X API
import tweepy

client = tweepy.Client(bearer_token="OFFICIAL_X_BEARER_TOKEN")
user = client.get_user(username="elonmusk").data
tweets = client.get_users_tweets(
    user.id,
    max_results=20,
    tweet_fields=["created_at", "public_metrics"],
    expansions=["author_id"],
).data

# After: requests + GetXAPI
import requests

resp = requests.get(
    "https://api.getxapi.com/twitter/user/tweets",
    params={"userName": "elonmusk"},
    headers={"Authorization": f"Bearer {GETXAPI_KEY}"},
)
tweets = resp.json()["tweets"]

The GetXAPI version is roughly half the lines, returns full author and engagement data inline (no expansions, no field selection), and costs ~100x less per tweet. For the full feature-by-feature breakdown, see Twitter API v2 vs GetXAPI.

Build a Python SDK Wrapper (Drop-in Class)

A 30-line Python class wraps the most common GetXAPI endpoints into a reusable client that handles connection pooling via requests.Session, sets the Bearer auth header once, and exposes typed methods for user lookups, search, timeline fetches, followers, replies, tweet creation, and DMs.

For larger projects, wrap the API in a small client class. Save this as getxapi_client.py and import it from anywhere:

import os
import requests
from typing import Optional

class GetXAPI:
    BASE = "https://api.getxapi.com"

    def __init__(self, api_key: Optional[str] = None, timeout: int = 15):
        self.key = api_key or os.environ["GETXAPI_KEY"]
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers["Authorization"] = f"Bearer {self.key}"

    def _get(self, path: str, **params) -> dict:
        resp = self.session.get(f"{self.BASE}{path}", params=params, timeout=self.timeout)
        resp.raise_for_status()
        return resp.json()

    def _post(self, path: str, **body) -> dict:
        resp = self.session.post(f"{self.BASE}{path}", json=body, timeout=self.timeout)
        resp.raise_for_status()
        return resp.json()

    def user(self, username: str) -> dict:
        return self._get("/twitter/user/info", userName=username)["data"]

    def search(self, query: str, product: str = "Latest") -> list[dict]:
        return self._get("/twitter/tweet/advanced_search", q=query, product=product).get("tweets", [])

    def user_tweets(self, username: str) -> list[dict]:
        return self._get("/twitter/user/tweets", userName=username).get("tweets", [])

    def followers(self, username: str) -> list[dict]:
        return self._get("/twitter/user/followers", userName=username).get("followers", [])

    def replies(self, tweet_id: str) -> list[dict]:
        return self._get("/twitter/tweet/replies", tweetId=tweet_id).get("replies", [])

    def post_tweet(self, text: str, login_cookies: str) -> dict:
        return self._post("/twitter/tweet/create", text=text, loginCookies=login_cookies)


# Usage
client = GetXAPI()
print(client.user("naval")["name"])
print(len(client.search("from:patio11", )))

That's a 30-line SDK that handles connection pooling (via requests.Session), timeouts, auth, and the most common endpoints. Extend it with pagination, retries, and async variants as your needs grow.

The cheapest Twitter API. Try it free.

$0.05 per 1,000 tweets. $0.10 free credits. No credit card required.

Get Your Python Twitter API Key

GetXAPI gives every new account $0.10 in free credits at signup, with no credit card required, enough to run every snippet in this tutorial. Sign up with Google or email, copy your Bearer key, and your first Python call is one minute away.

Get your API key → · View pricing · Cost calculator

For the official-route walkthrough (developer console, OAuth credentials, common rejection reasons), see How to Get a Twitter API Key (2026 Step-by-Step). For the full feature comparison against the official API, read Twitter API v2 vs GetXAPI. For advanced search operator syntax used in the q parameter throughout this guide, see the Twitter search operators reference. For a full breakdown of per-call costs at different volumes, see the Twitter API cost guide.


Production Checklist Before You Ship

Eight checks catch the most common production failures before they cost you credits or cause silent data gaps: API key loaded from env, retry logic covering 429 and 5xx, cursor-based stop condition on pagination, a max-pages safety cap, write-endpoint token rotation on 401, no raw key or token in logs, date-range chunking for large search jobs, and tweet-ID deduplication across overlapping workers.

Before taking any Python Twitter integration to production, run through these checks:

  • API key is loaded from an environment variable, not hardcoded in source
  • Retry logic handles 429, 502, and 503 with exponential backoff
  • Pagination uses has_more as the stop condition, not a hardcoded page count
  • A maxPages safety limit prevents infinite loops on runaway cursors
  • Auth tokens for write endpoints are stored in environment variables and rotated on 401
  • Logs never print the raw API key or auth_token values
  • Date-range chunking is used for any query expecting more than 50 pages of results
  • Deduplication by tweet ID is applied when multiple workers or query chunks overlap

This checklist captures the most common production gaps in Twitter API Python integrations.


Common Python Mistakes and How to Avoid Them

Six mistakes account for most silent failures in Twitter API Python projects: relying on next_cursor emptiness instead of has_more for pagination stop logic, hardcoding the wrong response key, retrying permanent 4xx errors, skipping explicit request timeouts, re-fetching the same user profile on every tweet, and using search where user/tweets is the correct endpoint.

These mistakes come up repeatedly in Twitter API Python projects. Most are silent: they don't raise exceptions, they just return wrong or incomplete data.

Mistake 1: Not checking has_more before paginating

# Wrong: this stops when next_cursor is empty, but an empty cursor doesn't always mean no more data
while data.get("next_cursor"):
    ...

# Right: check has_more as the primary signal
while data.get("has_more"):
    cursor = data["next_cursor"]
    ...

Mistake 2: Hardcoding the result key

Different endpoints return data under different keys: tweets, followers, replies, users. If you hardcode data["tweets"] on a follower endpoint, you get a KeyError.

# Fragile: breaks on non-tweet endpoints
tweets = data["tweets"]

# Safe: handle multiple possible keys
items = (
    data.get("tweets")
    or data.get("followers")
    or data.get("replies")
    or data.get("users")
    or []
)

Mistake 3: Retrying permanent errors

Retrying a 401 (bad API key) three times wastes three API calls. Retrying a 404 (user account suspended or deleted) wastes credits on data that does not exist. Only retry 429, 502, 503, and network timeouts.

Mistake 4: Not setting a request timeout

Without a timeout, a single hung request can block your entire pipeline indefinitely. Always pass timeout=15 (or appropriate seconds) to requests.get(). For long-running jobs, 15 seconds is a safe default; bump to 30 only if you are fetching large paginated results on slow connections.

Mistake 5: Re-fetching profiles on every tweet

If you fetch 1,000 tweets and each tweet has a unique author, that is up to 1,000 user lookups at $0.001 each. Cache the profiles by username and only re-fetch when the TTL expires. A simple dict with timestamps cuts this by 80% or more on typical datasets where popular accounts appear repeatedly.

Mistake 6: Using search for timeline fetches

from:username in a search query and user/tweets for the same user return the same data, but via different pathways. The search path filters by the web search index (which may lag by a few minutes), while user/tweets fetches directly from the user's timeline. For real-time monitoring of a specific account, user/tweets is more reliable. For multi-account or complex filter queries, search is the right tool. Using search when you only need one user's timeline wastes credits because you get ~20 results per call on search versus up to 20 per call on user/tweets, with no advantage for single-account fetches.

For a full list of production scraping patterns including proxy strategy, auth token management, and cost optimization across all 35 GetXAPI endpoints, see the Twitter scraping best practices guide.


Twitter API Python Ecosystem in 2026

The Python library landscape for Twitter data has consolidated since 2023 into two viable choices for production: requests plus GetXAPI for data collection at $0.001 per call, and tweepy against the official X API for OAuth user-delegated flows. snscrape and twint are effectively broken, and thin wrapper libraries like twitter-api-v2 on PyPI add an object-oriented layer without changing the underlying official API cost model.

The Python library landscape for Twitter data has consolidated significantly since 2023. Here is where things stand:

Library Status When to use
requests + GetXAPI Active, recommended Production data collection at any scale
tweepy (v4) Active, maintained OAuth user-delegated flows only
httpx + GetXAPI Active, recommended Async/concurrent data collection
snscrape Mostly broken Historical reference only
twint Archived, broken Not recommended
twitter-api-v2 (PyPI) Thin wrapper, maintained When you prefer an object-oriented tweepy alternative

The clearest signal for which path to choose: if you are building a consumer-facing app where users log in with their X account, you need tweepy and the official OAuth flow. For everything else (data collection, analytics, monitoring, bots, dashboards, research), requests plus GetXAPI is faster to set up, cheaper to run, and requires far less error-handling scaffolding. For a detailed operator reference for the q parameter used in search throughout this guide, see the Twitter search operators guide.


Twitter API Python FAQ for 2026

These eight questions address the most specific setup, cost, and operational details that come up when Python developers integrate with the Twitter API in 2026: fastest data path, SDK availability, academic research access, key rotation on 401, tweet storage patterns, the advanced_search rate limit, write action mechanics, and Python version compatibility.

These are the questions that come up most often when Python developers start integrating with the Twitter API in 2026.

What is the fastest way to get Twitter data in Python in 2026? Sign up at getxapi.com (30 seconds, no approval queue), copy your Bearer key, run pip install requests, and make your first call. The entire path from "I need Twitter data" to "I have Twitter data" takes under five minutes.

Does GetXAPI have a Python SDK? No official SDK, but the drop-in class in the SDK wrapper section above covers the most common endpoints in 30 lines. For most data-collection workloads, requests.Session with a Bearer header is enough, and adding a formal SDK layer adds complexity without benefit.

Can I use GetXAPI for academic research? Yes. The data you get is the same public tweet data as the official X API's Academic Research access. The main difference is that Academic Research access provides full-archive search (tweets older than 7 days) and GetXAPI's advanced_search endpoint is limited to the rolling 7-day window (or historical by date-range for accounts with historical indexing). For most research use cases, the 7-day window plus date-range chunking covers the data you need at a fraction of the cost.

What should I do when my API key stops working? A 401 response means the key is invalid or revoked. Log into the GetXAPI dashboard, check whether your credits are exhausted (which blocks new calls until you top up), generate a new key if needed, and update your environment variable. Never hardcode the key in source; always load it from an environment variable so rotation is a single config change with no code redeploy required.

How do I store tweets I scrape in Python? The most common pattern is to write tweet dicts to a local JSON Lines file for small batches, or insert into a database (PostgreSQL, SQLite, or a document store like MongoDB) for anything you plan to query later. The tweet response objects from GetXAPI are standard Python dicts and can be serialized to JSON with json.dumps() without any transformation.

Is there a rate limit I need to respect when using GetXAPI in Python? GetXAPI has a 50-call-per-15-minute platform limit on the advanced_search endpoint. For most workloads this is not a binding constraint. If you need to run more than 50 concurrent calls in a 15-minute window, split across multiple time windows or add a delay between batches. For context, 50 calls returns roughly 1,000 tweets, which is a meaningful batch for most monitoring or research jobs.

Can I use Python to send tweets automatically via GetXAPI? Yes. The POST /twitter/tweet/create endpoint creates tweets when you pass your X login cookies as the loginCookies parameter. The cookies are used in-flight to authorize the tweet and are never stored by GetXAPI. For the full DM send workflow, see the Twitter DMs via API guide.

What Python version is required? Python 3.8 or higher. The type hints in the snippets use list[dict] (lowercase, 3.9+) but you can replace with List[Dict] from typing for 3.8 compatibility. The httpx async examples require Python 3.7+. All production snippets in this guide are tested on Python 3.11.

How do I handle the x-rate-limit-reset header in Python? On GetXAPI you rarely need to. If you do hit a 429, the Retry-After header gives you the number of seconds to wait. On the official X API, parse x-rate-limit-reset as a UTC Unix timestamp and sleep until that time. A utility function: wait = max(0, int(r.headers.get("x-rate-limit-reset", time.time())) - time.time()); time.sleep(wait + 1). The +1 adds a one-second buffer for clock skew. For the complete patterns around rate limits on both APIs, see the Twitter scraping best practices guide. One additional note: if your pipeline runs on a schedule (cron job, cloud function, GitHub Actions), add a try/except requests.exceptions.Timeout around every call and log the timeout before retrying. Timeouts are the single most common silent failure in scheduled Twitter scraping jobs, they do not raise an exception by default unless you pass timeout= explicitly, and without that parameter a hung network call can block your entire job from completing until the OS-level TCP timeout fires, which can take minutes. Always set an explicit timeout on every request.


Pricing data verified May 6, 2026 from the official X API pricing page and GetXAPI pricing. All Python snippets tested against live GetXAPI endpoints. snscrape status sourced from the snscrape GitHub repository (paused active development 2023).

Frequently Asked Questions

For most use cases, plain `requests` against GetXAPI is the best Python integration in 2026. It costs ~100x less per tweet than `tweepy` against the official X API, takes 30 seconds to set up, and handles search, user lookups, follower exports, replies, and DMs without OAuth scaffolding. Use `tweepy` only when you specifically need OAuth user-delegated flows (apps where end users sign in with their X account).

`snscrape` is largely broken in 2026. The maintainers paused active development in late 2023 after X tightened its anti-scraping defenses, and most endpoints including search, user timelines, and follower lists are unreliable or fully broken. Several community forks attempted patches but they fail intermittently because they depend on undocumented web UI structure that X can change without notice. For any production workload, use a documented HTTP API, either the official X API or GetXAPI, both return stable JSON responses regardless of UI changes. The [Twitter scraping best practices guide](/blogs/getxapi-best-practices) covers the recommended production stack in detail.

GetXAPI at $0.001 per call (~20 tweets), about $0.05 per 1,000 tweets, is the cheapest mainstream Python-friendly Twitter API. The official X API costs $0.005 per post read (about $5 per 1,000 tweets), so GetXAPI is roughly 100x cheaper for read-heavy data collection. New GetXAPI accounts get $0.10 in free credits at signup, which is enough to test every endpoint before committing.

For the official X API: respect `x-rate-limit-remaining` headers, sleep until `x-rate-limit-reset` on 429s, and run separate queues per endpoint window. For GetXAPI: the simple loop is enough, there are no platform-level rate caps, so production code is shorter. The full headers and pattern reference is in the [Twitter API rate limits comparison](/twitter-api-rate-limits).

Yes, `tweepy` is still maintained, but it's married to the official X API, every cost, rate-limit, and authentication constraint of the official API also applies to `tweepy`. The library itself is fine; the underlying API economics make it expensive for data-collection workloads.

There's no separate "Twitter API" package, the API is HTTP. To use the GetXAPI Twitter API in Python, run `pip install requests` and authenticate with a single Bearer header. To use the official X API, run `pip install tweepy` and configure OAuth credentials.

Only if you go through the official X API. Sign up for a developer account at `console.x.com`, get an approved use case, generate Bearer + OAuth credentials, and configure them in `tweepy`. To skip all of that, use GetXAPI, sign up with email, copy your Bearer key, and start making Python requests immediately. For more on the credential differences, see [What is a Twitter API key?](/twitter-api-key).

Yes. Use `httpx.AsyncClient` (or `aiohttp`) to make concurrent requests. With GetXAPI you can run dozens of requests in parallel without coordinating around rate-limit windows. Against the official X API you need a semaphore plus per-endpoint window tracking to avoid burst-throttling, see the async section above for a working example.

Check out similar blogs

More guides on the Twitter/X API, scraping, and pricing.

How to scrape Twitter/X in 2026: an end-to-end workflow for tweets, profiles, followers, search, and media through a per-call read API
Twitter APIX API

How to Scrape Twitter/X in 2026 (Tweets, Profiles, Followers)

How to scrape Twitter/X in 2026: the legal line, why libraries and browser scrapers break, and a runnable per-call API workflow for tweets, profiles, followers, search, and media.

GetXAPI·
How to scrape tweets in 2026: the legal line on public data and a read-API fetch pattern that does not get blocked
Twitter APIX API

How to Scrape Tweets in 2026 (Without Getting Blocked)

How to scrape tweets in 2026 without getting blocked: why browser scraping breaks, where the legal line on public data sits, and a runnable read-API fetch script.

GetXAPI·
Twitter trends API tutorial: pull trending topics and hashtags by location in 2026
Twitter APIX API

Twitter Trends API: Pull Trending Topics by Location in 2026

A 2026 guide to building a Twitter trends API: pull trending topics and hashtags by location using a per-call search endpoint, with runnable Python and curl.

GetXAPI·
Twitter API tutorial 2026 complete developer guide, pricing collapse era, with auth flows, endpoints, code samples, and cost math
Twitter APIX API

Twitter API Tutorial 2026: The Complete Developer Guide

The 2026 Twitter API tutorial built after the pricing collapse. Auth, endpoints, code, rate limits, real costs, and the alternative when official gets too expensive.

GetXAPI·
Twitter Article API 2026 complete tutorial: all 7 endpoints, Python + Node.js code, Premium gate explained
Twitter APIX API

Twitter Article API in 2026: Create, Publish, and Distribute Long-Form Notes

Complete 2026 tutorial for the Twitter Article API. All 7 endpoints, working Python and Node.js code, the Premium gate explained, draft vs published state machine.

GetXAPI·
How to scrape the full tweet history of any public X account in 2026, past the 3,200-tweet timeline limit, using date-window search and cursor pagination
Twitter APITweet History

Scrape Full Tweet History of Any Account in 2026 (Beyond the 3,200 Limit)

Why the X timeline stops at 3,200 tweets and how to pull an account's full history with date-window search, cursor pagination, and dedup. Live-tested code in Python and curl.

GetXAPI·
Building a Twitter bot in 2026, no-code and Python paths, runnable code, and the real X API cost reality after the free tier ended
Twitter BotX Bot

How to Build a Twitter Bot in 2026: The Complete Guide

Build a Twitter bot in 2026 with no-code or Python. Working Tweepy and requests code, auth explained, and the cheap API path at $0.05 per 1,000 reads.

GetXAPI·
How to post tweets via API with authentication in 2026 using a registered X auth_token, no developer account required
Twitter APIX API

Post Tweets via API With Authentication in 2026 (No Developer Account)

Post tweets, threads, and media through an API without an X developer account. The auth_token model, working Python and Node code, rate-limit safety, and per-call costs.

GetXAPI·