X XDK Python Tutorial: X's Official SDK, Tested (2026)
We ran xdk 0.10.6 for this X XDK Python guide: install, bearer auth, search_recent, a user lookup, capped paging, and how it differs from Tweepy.
Tarun Khatri
Published · Updated · 6 min read
X XDK Python is X's official Python SDK: install it with pip install xdk, then call client.posts.search_recent with a bearer token.
This guide is for Python developers choosing between the official X (Twitter) SDK and Tweepy. We have no X key, so on 22 October 2026 we ran each snippet against a local stub, plus real calls to X with a fake token.
Your first search:
import os
from xdk import Client
client = Client(bearer_token=os.environ["X_BEARER_TOKEN"])
for page in client.posts.search_recent(query="from:XDevelopers", max_results=10):
for post in page.data or []:
print(post.id, post.text)
break # one page only: each post costs $0.005
- Install xdkpip install xdk==0.10.6
- Create a ClientPass your bearer token.
- Search recent postssearch_recent with post_fields.
- Look up a userusers.get_by_username
- Cap the pagescursor(...).pages(n)
Which X XDK languages exist?
Two: Python and TypeScript. X's Tools and Libraries page and its SDK generator's README list only these, both generated from X's OpenAPI spec.
| Language | Package | Version | Released |
|---|---|---|---|
| Python | xdk |
0.10.6 | 25 July 2026 |
| TypeScript | @xdevplatform/xdk |
0.6.6 | 25 July 2026 |
We read both from PyPI and npm on 22 October 2026. PyPI still tags the Python package "Alpha".
X lists no Go or Java XDK for the API. Its separate Chat XDK, for encrypted DMs, is on npm, but we found no Python package for it on PyPI.
Step 1: Install the X XDK Python package
It needs Python 3.8 or newer and pulls in Pydantic and requests:
python -m venv .venv && source .venv/bin/activate
pip install xdk==0.10.6
Skip xdk.__version__. X's install page says it prints the version, but 0.10.6 printed 0.1.0. Ask the metadata:
from importlib.metadata import version
print(version("xdk")) # 0.10.6
Step 2: Create the Client and pick your auth
Client holds your credentials and builds one sub-client per area, such as client.posts and client.users.
- Bearer token:
Client(bearer_token=...)reads public data. Our X API key guide shows where to copy it. - OAuth 1.0a:
Client(auth=OAuth1(...)), fromxdk.oauth1_auth, acts as your own account. - OAuth 2.0 PKCE:
OAuth2PKCEAuth, fromxdk.oauth2_auth, gets a user's token for you.
Step 3: Search recent posts with search_recent
search_recent calls X's recent search, which covers the last 7 days. It returns a generator, so next() sends one request:
pages = client.posts.search_recent(
query="python lang:en -is:retweet",
max_results=10,
post_fields=["created_at", "public_metrics", "author_id"],
expansions=["author_id"],
user_fields=["username"],
)
first = next(pages)
for post in first.data or []:
print(post.id, post.created_at, post.public_metrics.like_count)
Our stub run printed:
1234567890123456789 2024-01-15T10:30:00.000Z 42
The SDK sent post.fields, X's newer name for tweet.fields. Three things tripped us up:
tweet_fieldsraisesTypeError. X's recent search quickstart and XDK pagination page still pass it.- Posts are Pydantic models.
post["id"]fails, so writepost.id. - The models are strict. X's own sample JSON failed validation, since the SDK requires
repost_countandimpression_count. Our stub serves the names in X's OpenAPI spec instead.
An open issue on the xdk-python repo reports the same strictness on live data: with referenced_posts requested, one repost fails a whole timeline page.
For operators and full-archive search, see our Twitter search API guide.
Step 4: Look up a user with get_by_username
Single-object methods return one response, not a generator:
user = client.users.get_by_username(
"XDevelopers", user_fields=["created_at", "public_metrics"]
).data
print(user.id, user.username, user.public_metrics.followers_count)
2244994945 xdevelopers 570842
Those are X's sample numbers from our stub. Live, X bills it as one user read: $0.010.
Step 5: Cap pages with the XDK pagination helpers
Looping over search_recent walks every page until X stops sending a next_token. Nothing in 0.10.6 caps it, and X bills each page.
cursor wraps a method so you can set a ceiling:
from xdk import cursor
search = cursor(client.posts.search_recent, "python lang:en", max_results=100)
for page in search.pages(3): # at most 3 requests
print(len(page.data or []))
for post in cursor(client.posts.search_recent, "python", max_results=100).items(250):
print(post.id)
Our stub served two pages. Each loop sent two requests, then stopped when the token ran out.
At 100 posts a page, pages(3) caps a run at $1.50.
X's pagination page says the iterator "Supports rate limit backoff to avoid 429 errors." We found none in 0.10.6's search code: a 429 raises requests.HTTPError. Only the streaming client retries.
If the XDK fails: the 401 and other errors
We sent this to X on 22 October 2026 with a fake token:
import requests
from xdk import Client
client = Client(bearer_token="not-a-real-token")
try:
next(client.posts.search_recent(query="from:XDevelopers"))
except requests.HTTPError as error:
print(error.response.status_code, error.response.json()["detail"])
401 Unauthorized
- No token at all raises
ValueErrorbefore anything is sent. - A wrong or regenerated token gets the
401above, as a plainrequests.HTTPError. - There's no
xdk.AuthenticationError. X's auth page names it, but 0.10.6 doesn't define it.
X XDK vs Tweepy: which should you use?
Both call the same API at the same price. They differ in names and safety rails:
| xdk 0.10.6 | Tweepy 4.17.0 | |
|---|---|---|
| Made by | X | Community |
| Search method | posts.search_recent |
search_recent_tweets |
| Field argument | post_fields |
tweet_fields |
| Page cap | cursor().pages(n) |
Paginator(limit=n) |
| On a 429 | Raises an error | Can wait and retry |
| Host | api.x.com | api.twitter.com |
Pick xdk if you want X's own names and methods generated from X's spec. Pick Tweepy if you want years of answers online and a built-in rate-limit wait. See our Tweepy tutorial.
The Weir route for read-only work
If you only read public posts, you can skip the SDK, the X app and its prepaid credits. We run Weir, a read-only REST API for public X data, so weigh this knowing that.
Plain requests is enough:
import os, requests
r = requests.post(
"https://api.weirapp.io/v1/x/search",
headers={"Authorization": f"Bearer {os.environ['WEIR_API_KEY']}"},
json={"fromUsers": ["XDevelopers"], "limit": 10},
timeout=60,
)
for post in r.json()["data"]:
print(post["id"], post["likeCount"], post["text"][:60])
Each post carries its author, so there's no includes step. Our free get_limits call on 22 October 2026 showed what a free account gets:
{
"tier": "free",
"rateLimitPerMinute": 30,
"maxMonitors": 1,
"maxWebhooks": 1,
"hourlySchedules": false
}
A search costs 1 credit per call plus 1 per post, and 5,000 credits a month are free:
When not to use Weir
- You post, reply or like. Weir only reads, while the XDK writes with OAuth.
- You need a live stream. The XDK's streaming client holds an open connection, and Weir has no stream.
- You need a contract with X itself. Use X's API, through the XDK or Tweepy.
- Price per post is all that matters. TwitterAPI.io lists $0.15 per 1,000 tweets, and it can post.
Weir isn't licensed by X, so its access can change.
FAQ
What is the X XDK?
The XDK, or X Developer Kit, is X's set of official SDKs for the X API v2. It comes in Python and TypeScript, both generated from X's OpenAPI spec. X's changelog dates the launch to 3 November 2025.
Is xdk the official X Python SDK?
Yes. X's docs call the Python XDK "our official client library" for the X API v2. Install it with pip install xdk. X still lists Tweepy, but under community libraries.
Is there a Go or Java XDK?
Not as of October 2026. X's SDK generator lists only Python and TypeScript, and its README uses Go only as an example of adding a language. For Go, X's docs point to community libraries.
Can I use the X Python SDK for free?
The SDK is free, but the API isn't. X's pricing page has you buy credits upfront, and each post read costs $0.005. With no token, the SDK raises an error before it sends a request.
Sources
All checked on 22 October 2026, with docs.x.com read as Markdown:
- X Tools and Libraries: https://docs.x.com/tools-and-libraries
- X Python XDK docs, with their install, authentication and pagination pages: https://docs.x.com/xdks/python/overview
- X recent search quickstart: https://docs.x.com/x-api/posts/search/quickstart/recent-search
- X OpenAPI spec 2.172, pricing and changelog: https://api.x.com/2/openapi.json, https://docs.x.com/x-api/getting-started/pricing and https://docs.x.com/changelog
- PyPI and npm: https://pypi.org/project/xdk/, https://www.npmjs.com/package/@xdevplatform/xdk and https://www.npmjs.com/package/@xdevplatform/chat-xdk
- X's GitHub: https://github.com/xdevplatform/xdk and https://github.com/xdevplatform/xdk-python/issues/7
- Tweepy 4.17.0: https://pypi.org/project/tweepy/ and https://github.com/tweepy/tweepy/blob/v4.17.0/tweepy/client.py
- TwitterAPI.io: https://twitterapi.io/pricing and https://docs.twitterapi.io/api-reference/endpoint/create_tweet_v2
- Weir billing: https://docs.weirapp.io/billing
- Our runs: xdk 0.10.6 against a local stub, X's 401 to a fake token, and Weir's free get_limits