Contents
To use the Twitter API in Python in 2026, install X's official SDK with
pip install xdkrequestshttps://api.x.com/2This guide gives you working Twitter API Python code for all three official routes, shows how to handle 429s, and prices each example. It ends with a fourth option for jobs the official API no longer covers.
Three ways to use the Twitter API in Python
| Option | Install | Best for | Status (checked October 2026) |
|---|---|---|---|
| xdk (official SDK) | pip install xdk | New projects, newest endpoints | 0.10.6 on PyPI, July 2026, MIT |
| Tweepy | pip install tweepy | Existing code, big community | 4.17.0, July 2, 2026, 11k+ GitHub stars |
| requests | pip install requests | Full control, no dependencies | Always works if you can read the docs |
X launched xdk on February 6, 2026, alongside pay-per-use pricing. It's generated from X's OpenAPI spec, supports Python 3.8 and up, and handles Bearer tokens, OAuth 2.0 with PKCE and OAuth 1.0a (Python XDK docs). Tweepy has been the community default for years and still ships releases (Tweepy on PyPI).
Older tutorials were written for the free tier and API v1.1, so their auth steps and free-tier assumptions will probably be wrong. The top YouTube results for this search still include a 2022 Tweepy series.
Before you write code: credentials and cost
You need an app at console.x.com. Its "Keys and tokens" page lets you generate:
- a Bearer token for read-only, app-level calls;
- an OAuth 2.0 client ID (and secret) to act on behalf of a user;
- an OAuth 1.0a API key, secret, access token and access token secret, the legacy user-context method.
Then add credits. Once your balance can't cover a request, X denies it. At October 2026 rates (X API pricing):
| Call | Cost |
|---|---|
| Read a post | $0.005 |
| Read a user, or one follower record | $0.010 |
| Read your own data (Owned Reads) | $0.001 |
| Create a post | $0.015 ($0.20 with a URL) |
| Send a DM | $0.015 |
Keep your tokens in environment variables, not in the script:
export X_BEARER_TOKEN="..."
Set a spending limit in the console as well. A loop with a pagination bug will spend your whole balance without stopping. One developer on r/openclaw, u/NHI10, watched an agent do exactly that: "After ~10 minutes and ~1000 tweets from one user, $5 was gone".
Option 1: the official xdk SDK
pip install xdk
To look up a user and read their recent posts with a Bearer token:
import os from xdk import Client client = Client(bearer_token=os.environ["X_BEARER_TOKEN"]) # 1 user read = $0.010 user = client.users.get_by_username( "XDevelopers", user_fields=["description", "public_metrics"] ) print(user.data.id, user.data.public_metrics) # Search_recent returns an iterator of pages; each post returned = $0.005 for page in client.posts.search_recent( query="from:XDevelopers -is:retweet", max_results=10, post_fields=["created_at", "public_metrics"], ): for post in page.data or []: print(post.id, post.text[:80]) break # stop after one page, or the iterator keeps paging (and billing)
In xdk the field parameter is
post_fieldstweet_fieldsuser.data.usernamePay attention to
breakclient.users.get_followers(id=..., max_results=100)Option 2: tweepy
pip install tweepy
Here are the same two calls in Tweepy:
import os import tweepy client = tweepy.Client( bearer_token=os.environ["X_BEARER_TOKEN"], wait_on_rate_limit=True, # sleeps through 429s instead of raising ) user = client.get_user(username="XDevelopers", user_fields=["public_metrics"]) print(user.data.id, user.data.public_metrics) tweets = client.search_recent_tweets( query="from:XDevelopers -is:retweet", max_results=10, tweet_fields=["created_at", "public_metrics"], ) for tweet in tweets.data or []: print(tweet.id, tweet.text[:80])
For scripts, the most useful part of Tweepy is
wait_on_rate_limit=TrueIf you already have Tweepy code, keep it. For new code, xdk follows X's API spec directly, so newer endpoints such as Articles, the Activity API and news show up there first.
Option 3: plain requests against API v2
This version skips the SDK and uses one helper that handles rate limits explicitly:
import os import time import requests BASE = "https://api.x.com/2" HEADERS = {"Authorization": f"Bearer {os.environ['X_BEARER_TOKEN']}"} def x_get(path, **params): while True: r = requests.get(f"{BASE}{path}", headers=HEADERS, params=params, timeout=30) if r.status_code == 429: # rate limited: wait until the window resets reset = int(r.headers.get("x-rate-limit-reset", time.time() + 60)) time.sleep(max(reset - time.time(), 1) + 1) continue if not r.ok: # bad token, app not enrolled, out of credits, etc. raise RuntimeError(f"{r.status_code}: {r.text}") return r.json() user = x_get("/users/by/username/XDevelopers", **{"user.fields": "public_metrics"}) uid = user["data"]["id"] # Up to 500 followers: 5 pages x 100 records x $0.010 = $5.00 followers, token = [], None for _ in range(5): params = {"max_results": 100, "user.fields": "description,public_metrics"} if token: params["pagination_token"] = token page = x_get(f"/users/{uid}/followers", **params) followers += page.get("data", []) token = page.get("meta", {}).get("next_token") if not token: break print(len(followers), "followers fetched")
Field parameters have dotted names (
user.fieldstweet.fields**{...}Posting, DMs and user context
A Bearer token is enough to read public data. Posting and sending DMs need a user token, since you are acting as an account.
With OAuth 2.0, request scopes such as
tweet.read tweet.write users.read dm.write offline.accessOAuth2PKCEAuthimport os from xdk import Client from xdk.posts.models import CreateRequest from xdk.direct_messages.models import CreateByParticipantIdRequest client = Client(bearer_token=os.environ["X_USER_ACCESS_TOKEN"]) # OAuth 2.0 user token # $0.015 per post ($0.20 if the text contains a URL) client.posts.create(body=CreateRequest(text="Shipping a small update today.")) # $0.015 per DM client.direct_messages.create_by_participant_id( participant_id="2244994945", body=CreateByParticipantIdRequest(text="Thanks for the feedback on the beta."), )
Tweepy's equivalents are
client.create_tweet(text=...)client.create_direct_message(participant_id=..., text=...)Check the self-serve rules before you build anything that writes. Since February 23, 2026, a programmatic reply is allowed only when the original author @mentioned or quoted your account. Since April 20, 2026, following, likes and quote-posts are gone from every self-serve tier (X changelog). DM sends are capped at 15 requests per 15 minutes per user and 1,440 per day (X rate limits).
client.users.follow_userHandling 429s and 402s in Python
Every script eventually runs into two failure modes.
The first is rate limits, which come back as HTTP 429. Each endpoint has a window, usually 15 minutes. Read
x-rate-limit-remainingx-rate-limit-resetx_getThe second is running out of credits. X's developer agreement says requests "will be denied until your credit balance is sufficient". X doesn't document which status code that comes back as, so check the error body for the credit message rather than matching one code. Don't retry those in a loop. Alert yourself and stop.
New apps also hit a third one:
client-not-enrolledOption 4: a third-party API with requests
Some Python projects don't fit the official API at all. Reads at volume cost too much, or the job needs follows, likes or DMs across several accounts.
There is a fair case for staying official anyway. It is the only route fully inside X's terms, which forbid accessing X except through published interfaces (X Terms). Unofficial Python libraries that log in as you break often. u/Icy-Care-353 on r/webdev tried one and found "it's not maintained anymore and full of bugs". If your project is public, or acts on behalf of other people, stay official and budget for it.
If the job is outreach or engagement from accounts you own, a managed third-party API is the middle path. The XAutoDM API is one of them. It is built for writes across connected X accounts, so if you only need to bulk-read tweets, it won't be the cheapest option. The same
requestsimport os import uuid import requests API = "https://api.xautodm.com/v1" HEADERS = {"Authorization": f"Bearer {os.environ['XAUTODM_API_KEY']}"} # Read a profile: 5 credits profile = requests.get(f"{API}/users/nasa", headers=HEADERS, timeout=30).json() print(profile["data"]) # Send a DM from one of your connected accounts: 10 credits r = requests.post( f"{API}/dm/send", headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())}, # retries never double-send json={ "account_id": "acc_1a2b3c", "recipient_username": "jack", "text": "Loved your thread on onboarding. Mind if I share one idea?", }, timeout=30, ) print(r.json()) # meta shows credits_charged and credits_remaining
Follows and likes cost 5 credits each (
POST /v1/actions/follow/v1/actions/likeWhich library to pick
- For a new script that reads public data, use xdk with a Bearer token and a page cap.
- For an existing Tweepy codebase, stay on Tweepy 4.17 and turn on .
wait_on_rate_limit - For a serverless function, or when you want minimal dependencies, use with the helper above.
requests - For analytics on your own account, any of the three works, as long as you hit Owned Reads at $0.001.
- For DMs, follows and likes across several accounts, use a write-focused third-party API.
Start by running the xdk example with a fresh Bearer token. Check the cost in the console afterwards, and only then point it at real volume. If your project needs writes across accounts, grab an XAutoDM API key and run the
requestsFrequently asked questions
Is tweepy still maintained in 2026?
Yes. Tweepy 4.17.0 came out on July 2, 2026, and the project has over 11,000 GitHub stars. It supports X API v2 through tweepy.Client. X also publishes its own official Python SDK now, xdk, which is generated from the API's OpenAPI spec and gets newer endpoints first.
What is the official Python SDK for the X API?
It's xdk, part of the X Developer Kit that launched in February 2026. Install it with pip install xdk. It supports Bearer tokens, OAuth 2.0 with PKCE and OAuth 1.0a, and it handles pagination for you. It is MIT licensed. As of October 2026 the latest version on PyPI was 0.10.6.
Can I use the Twitter API in Python for free?
The code and libraries are free. The X API calls are not. Since February 2026 the X API has been pay-per-use, for example $0.005 per post read and $0.015 per post created. New paying accounts can earn up to $70 in starter credits, which covers building and testing a script.
How do I send a DM with Python?
Through the official API, you need an OAuth 2.0 user token with the dm.write scope. Then call client.direct_messages.create_by_participant_id in xdk or client.create_direct_message in Tweepy. Each DM costs $0.015, and the limit is 15 requests per 15 minutes per user.
Your next customer is already on X.
Find the people talking about what you sell, message them on a safe schedule, and turn the replies into booked calls.
- Scrape leads from any tweet, keyword or X List
- Auto-DM new followers and people who engage
- Follow-ups that stop the moment someone replies
- Safe daily limits and warm-up, built in
- Every reply tracked through to a booked call
Plans from $29/mo · cancel anytime.
Related posts
Ready to automate your Twitter DMs?
Start sending personalized DM campaigns to your target audience today. Get higher response rates and more leads than cold emails.








