Install
Authenticate
Basic Example
Search tweets and write durable JSON Lines handoff rows:Workflow: Search Tweets to CSV, JSON Lines, or XLSX
This job is for data scripts, notebooks, scheduled workers, and agent tools that need tweet search results in a durable handoff file. It callsGET /x/tweets/search through client.x.tweets.search, uses the generated TweetSearchParams shape, and writes analyst-friendly CSV plus JSON Lines for queues, warehouses, and replayable processing.
q
Python argument
q maps to REST q. Use it for the required X search query with keywords, handles, hashtags, or operators.limit
Python argument
limit maps to REST limit. Use it as a 1 to 200 upper bound for a bounded pull. If page.has_next_page is true, keep the same q, filters, query_type, and limit when you continue with page.next_cursor.cursor
Python argument
cursor maps to REST cursor. Pass the opaque cursor from page.next_cursor to request the next page.since_time
Python argument
since_time maps to REST sinceTime. Use it as the ISO 8601 lower time bound.until_time
Python argument
until_time maps to REST untilTime. Use it as the ISO 8601 upper time bound.query_type
Python argument
query_type maps to REST queryType. Use Latest for chronological results or Top for engagement-ranked results.Returned Data & Handoff
client.x.tweets.search returns a PaginatedTweets Pydantic model:
page.tweets
JSON field
tweets. Contains SearchTweet records with id, text, optional author, created_at, like_count, reply_count, retweet_count, quote_count, bookmark_count, view_count, and is_note_tweet when available.page.has_next_page
Python field
page.has_next_page. JSON field has_next_page. Tells your script whether another page exists.page.next_cursor
JSON field
next_cursor. Store it only when page.has_next_page is true. For bounded pulls that return fewer tweets than limit, pass it back as cursor with the same query, filters, query_type, and limit.page.tweets into CSV rows for analysts and JSON Lines rows for queues and data lakes in xquik-tweet-search.jsonl. Load the same projected rows into pandas or openpyxl when account teams need an XLSX workbook. Store tweet_id, author_username, engagement counts, page_index, page_cursor, next_cursor, and has_next_page so a script can resume from the last saved cursor without replaying raw SDK models. For explicit limit pulls, resume with the same query, filters, query_type, and limit; only cursor changes.
Workflow: Follower Export to CSV, JSON, or XLSX
Use this workflow when a Python script, notebook, worker, or agent tool needs an owned follower list for a CRM import, warehouse load, analyst CSV file, XLSX workbook, or resumable JSON handoff. It callsPOST /extractions/estimate through client.extractions.estimate_cost, creates the job with client.extractions.run, reads saved rows with client.extractions.retrieve, and downloads files with client.extractions.export_results.
client.extractions.run returns the queued 202 Accepted receipt from POST /extractions: REST id, toolType, and status: "running" as Python job.id, job.tool_type, and job.status. Store job.id immediately, then poll client.extractions.retrieve before reading pages or calling client.extractions.export_results. Credit reservation happens after the job starts. If available credits changed since estimate_cost, the run can fetch only the affordable count before export or mark the job failed with insufficient_credits.follower_explorer requires target_username. Persist job.id, target_username, estimate.estimated_results, and estimate.source before polling so a notebook restart, queue retry, or worker restart can resume the same follower export. client.extractions.retrieve returns results, has_more, and next_cursor; pass next_cursor back as after when you need stored JSON pages before exporting files. Use xquik-followers.jsonl for queue replay or warehouse loads, xquik-followers.json for app ingestion, xquik-followers.csv for CRM import, and xquik-followers.xlsx for analyst handoff. Map exported User ID or row xUserId as the CRM unique key. Cost: 1 credit per follower extracted or returned. Exports are free after the extraction job exists.
Workflow: Tweet Replies to CSV, JSON, or XLSX
Use this workflow when a Python script, notebook, worker, or agent tool needs every reply under one tweet as a saved extraction, JSON Lines handoff, or CSV/JSON/XLSX file export. It usesclient.extractions.estimate_cost, run, retrieve, and export_results.
Reuse the polling, row pagination, and export structure from the follower workflow. Only the tool type, target field, and output filenames change:
reply_extractor requires target_tweet_id. client.extractions.retrieve returns results, has_more, and next_cursor; the shared pagination loop passes next_cursor back as after. Use xquik-replies.jsonl for queue replay or warehouse loads, xquik-replies.json for app ingestion, xquik-replies.csv for CRM import, and xquik-replies.xlsx for analyst handoff. client.extractions.export_results supports csv, json, and xlsx for file handoff. Cost: 1 credit per reply extracted or returned.
Workflow: Post Media Tweets and DM Attachments
Use this workflow when a Python worker, notebook, support queue, or agent needs to post a media-backed tweet, reply with media, or send one uploaded media item in a DM. Tweet and reply media posts use public media URLs directly onclient.x.tweets.create. Send up to 4 image URLs or exactly 1 MP4 video URL up to 100 MB. Do not mix video with other media. Do not upload first when the media URL is already public.
tweet_id responses. Use with_raw_response.create when a write worker must branch on the REST 202 x_write_unconfirmed response, store writeActionId and chargedCredits, and poll Get Write Action Status before sending another write.
reply_to_tweet_id:
media.media_id as the only media_ids item:
client.x.tweets.create returns tweet.tweet_id for confirmed posts. Raw create responses can also include the pending write fields above when confirmation is still running. client.x.media.upload returns media.media_id for DM attachments, and client.x.dm.send returns dm.message_id for support tickets, CRM records, queue jobs, or agent memory.
Keep DM body text in private systems. Shared logs, public artifacts, queue status, and agent handoffs should store message_id, optional media_id, account, user_id, and send status instead of full DM bodies. Leave reply_to_message_id unset even if generated SDK types expose it; the REST endpoint rejects DM reply threading.
Text-only tweet and reply writes cost 10 credits. Tweet media adds 2 credits per started MB across attached files. Uploading media costs 10 credits, and sending the DM costs 10 credits. Do not pass uploaded media.media_id values to client.x.tweets.create; that method uses media with public media URLs.
Cost, Limits & Retries
Tweet search costs 1 credit per tweet returned. If remaining credits cannot cover a boundedlimit request, the API can return fewer tweets; if 0 paid results are affordable, it returns 402 insufficient_credits. Read calls are rate-limited, and 429 responses include Retry-After.
The client retries connection errors, 408, 409, 429, and 5xx responses by default. Handle RateLimitError with backoff, and fix 400, 401, 403, 404, or 422 responses before retrying.
Error Handling
All SDK exceptions inherit fromx_twitter_scraper.APIError.
400 Bad Request
Throws
BadRequestError.401 Unauthenticated
Throws
AuthenticationError.403 Permission Denied
Throws
PermissionDeniedError.404 Not Found
Throws
NotFoundError.422 Unprocessable Entity
Throws
UnprocessableEntityError.429 Rate Limited
Throws
RateLimitError.5xx Server Error
Throws
InternalServerError.max_retries when constructing the client to change retry behavior.
Pagination
List endpoints return page models withhas_next_page and cursor fields.