Skip to main content
Use this workflow when a research, sales, support, or monitoring system needs tweets as rows. Xquik can search tweets by keyword, hashtag, author, language, date range, media type, or engagement filters with tweet_search_extractor, estimate the cost first, run the extraction job, then export CSV, JSON, or XLSX.

When to use this workflow

Spreadsheet export

Use tweet_search_extractor plus CSV or XLSX export when analysts need rows.

App ingestion

Use tweet_search_extractor plus paginated JSON results for queues, CRMs, or warehouses.

Latest page

Use GET /x/tweets/search when you only need the newest matching API page.

Cost control

Set resultsLimit on estimate and create requests before scraping.

Choose the right path

Saved tweet search export

Call POST /extractions/estimate, then POST /extractions when you need a reusable job ID, cost preview, CSV, JSON, or XLSX download.

Paginated extraction rows

Call GET /extractions/{id}?limit=1000&after={nextCursor} when a CRM, warehouse, queue, or agent needs saved JSON pages.

Live direct API page

Call GET /x/tweets/search?q={query} when you need cursor-driven pages, or one Tweet ID or X status URL lookup, without a stored extraction job.

Shell or SDK handoff

Use CLI, TypeScript, Python, or Go when code should own JSON Lines, CSV, or XLSX files such as xquik-tweet-search.jsonl.
Use extraction jobs for repeatable exports and audit trails. Use the direct API for low-latency pages, small app handoffs, or exact lookup from one stored Tweet ID or X status URL.
Estimate before large jobs. The 202 Accepted create response queues the job. It does not prove credits are reserved. Poll GET /extractions/{id} before fetching rows. The run can lower resultsLimit to the affordable result count. It can also finish as failed with insufficient_credits.

End-to-end export handoff

Store one checkpoint that carries the search request through estimate, job creation, JSON pagination, and file export:
{
  "workflow": "tweet_search_export",
  "request": {
    "toolType": "tweet_search_extractor",
    "searchQuery": "launch announcement",
    "language": "en",
    "sinceDate": "2026-05-01",
    "mediaType": "media",
    "resultsLimit": 500
  },
  "estimate": {
    "estimatedResults": 500,
    "creditsRequired": "500",
    "creditsAvailable": "77000",
    "allowed": true,
    "source": "resultsLimit"
  },
  "create_receipt": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "toolType": "tweet_search_extractor",
    "status": "running",
    "poll_path": "/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
  },
  "json_pages": {
    "limit": 1000,
    "page_cursor": null,
    "next_cursor": "990200",
    "has_more": true
  },
  "export_paths": {
    "csv": "/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=csv",
    "json": "/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=json",
    "xlsx": "/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=xlsx"
  },
  "normalized_row": {
    "tweet_id": "1893710452812718080",
    "tweet_text": "We launched the new workflow today.",
    "tweet_created_at": "2026-05-01T10:05:00.000Z",
    "author_user_id": "44196397",
    "author_username": "xquikcom",
    "export_format": "csv"
  },
  "handoff_state": "poll_until_completed_then_export"
}

Estimate checkpoint

Keep estimatedResults, creditsRequired, creditsAvailable, allowed, and source with the original query and filters.

Job checkpoint

Store the returned job id, status, and poll_path; do not expect result rows in the create response.

Cursor checkpoint

Store page_cursor, next_cursor, and has_more for JSON page loops, then pass nextCursor back as after.

Export checkpoint

Store the chosen CSV, JSON, or XLSX export_paths and the normalized row fields sent downstream.

Data you get

Tweet search exports include base user fields, tweet fields, engagement counts, and metadata when available.

Tweet author

User ID, username, display name, follower count, verified state, and profile image.

Tweet

Tweet ID, tweet text, tweet created time, and permalink.

Engagement

Likes, reposts, replies, quotes, views, and bookmarks.

Metadata

Language, source app, conversation ID, and attached media.

Step 1: Estimate tweets and credits

Call POST /extractions/estimate before scraping tweets. tweet_search_extractor requires searchQuery. Add resultsLimit when you want a sample or a hard cost cap.
curl -X POST https://xquik.com/api/v1/extractions/estimate \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "toolType": "tweet_search_extractor",
    "searchQuery": "launch announcement",
    "language": "en",
    "sinceDate": "2026-05-01",
    "mediaType": "media",
    "resultsLimit": 500
  }' | jq
The estimate returns allowed, estimatedResults, creditsRequired, creditsAvailable, and source. For tweet search scraping, source is resultsLimit when a cap is set and unknown when no cap is set.

Filter fields to operators

tweet_search_extractor merges structured fields into searchQuery before the job runs. Use fields when UI or SDK code owns filters; use advancedQuery when you already have a trusted X search operator string.

Author and mentions

fromUser becomes from:username, toUser becomes to:username, and mentioning becomes @username.

Dates and language

language becomes lang:en, sinceDate becomes since:YYYY-MM-DD, and untilDate becomes until:YYYY-MM-DD.

Media and engagement

mediaType accepts images, videos, media, or gifs; use minFaves, minRetweets, and minReplies for thresholds.

Replies and retweets

replies and retweets accept exclude, include, or only; verifiedOnly adds filter:verified.
exactPhrase quotes the value, excludeWords turns comma-separated words into -word filters, and advancedQuery is appended to the final query. For direct GET /x/tweets/search, put the same operators in q. A plain Tweet ID or X status URL in q is a direct lookup, not a saved extractor job.

Step 2: Run the tweet search extraction

Create the job with the same toolType, searchQuery, filters, and optional resultsLimit.
curl -X POST https://xquik.com/api/v1/extractions \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "toolType": "tweet_search_extractor",
    "searchQuery": "launch announcement",
    "language": "en",
    "sinceDate": "2026-05-01",
    "mediaType": "media",
    "resultsLimit": 500
  }' | jq
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "toolType": "tweet_search_extractor",
  "status": "running"
}
Store the creation response as a local handoff before polling:
{
  "job": "tweet_search_extraction",
  "tweet_search_extraction_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "search_query": "launch announcement",
  "filters": {
    "language": "en",
    "since_date": "2026-05-01",
    "media_type": "media"
  },
  "results_limit": 500,
  "status": "running",
  "handoff_created_at": "2026-05-16T03:25:00.000Z"
}
Poll by tweet_search_extraction_id; keep search_query, filters, and results_limit with the audit record. Do not wait for totalResults or createdAt in the create response; those fields arrive from GET /extractions/{id}.

Step 3: Poll job status

Poll GET /extractions/{id} until the job is completed or failed.
curl https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "x-api-key: xq_YOUR_KEY_HERE" | jq
Use the paginated response when your app wants JSON rows instead of a file download.

Step 4: Export CSV, JSON, or XLSX

Exports are free after the extraction job exists. Use CSV for spreadsheets, JSON for app ingestion, and XLSX for analyst handoff. CSV, JSON, and XLSX exports are capped at 100,000 rows.
curl -X GET "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=csv" \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -o tweet-search.csv
curl -X GET "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=json" \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -o tweet-search.json
curl -X GET "https://xquik.com/api/v1/extractions/a1b2c3d4-e5f6-7890-abcd-ef1234567890/export?format=xlsx" \
  -H "x-api-key: xq_YOUR_KEY_HERE" \
  -o tweet-search.xlsx

Step 5: Hand off rows

For API handoff, call GET /extractions/{id} with limit up to 1000 and pass nextCursor as after until hasMore is false. Store job, results, hasMore, and nextCursor. Normalize each tweet row before sending it downstream:
{
  "job": "tweet_search_export",
  "search_query": "launch announcement",
  "result_id": "b2c3d4e5-f6a1-7890-abcd-ef2345678901",
  "tweet_id": "1893710452812718080",
  "tweet_text": "We launched the new workflow today.",
  "tweet_created_at": "2026-05-01T10:05:00.000Z",
  "author_user_id": "44196397",
  "author_username": "xquikcom",
  "source": "tweet_search_extractor",
  "export_format": "json"
}
For direct API handoff, normalize tweets[].id, tweets[].text, tweets[].createdAt, tweets[].author.id, tweets[].author.username, has_next_page, and next_cursor. For JSON Lines, write one normalized tweet object per line to xquik-tweet-search.jsonl.

Direct tweet search API

Use GET /x/tweets/search when you need a paginated API response instead of a stored extraction job.
curl -G https://xquik.com/api/v1/x/tweets/search \
  --data-urlencode "q=launch announcement" \
  -H "x-api-key: xq_YOUR_KEY_HERE" | jq
The direct search API returns tweets, has_next_page, and next_cursor. Leave limit unset for a simple cursor-driven page loop, and pass next_cursor back as cursor. Set limit when you want Xquik to collect up to that count in one bounded request; if has_next_page is true, continue with the same query, filters, queryType, and limit, and set cursor to next_cursor. Cost is 1 credit per tweet returned. For account date windows, sinceTime and untilTime append since: and until: operators to the search query. A request such as q=from:username&sinceTime=2026-05-01&untilTime=2026-05-02 behaves like from:username since:2026-05-01 until:2026-05-02. Use queryType=Latest for chronological backfills. Add a keyword, hashtag, or other operator when you need normal search ranking. For bounded direct API requests with limit, a bare q=from:username and no sinceTime or untilTime is treated as a user timeline pull. It returns a single page with has_next_page: false. Add another search term or use fromUser with a keyword when you need search pagination for that user.

Failure handling

400 missing query

Send a non-empty q value for direct search, or searchQuery for tweet_search_extractor.

402 credits

Subscribe, add credits, lower direct limit, or lower extraction resultsLimit.

429 rate limit

Wait for retryAfter or the Retry-After header before retrying.

424 or 502 unavailable

Retry with exponential backoff and keep the same query, filters, cursor, or job ID.

Handoff checklist

Spreadsheet

Export format=csv or format=xlsx.

App ingestion

Export format=json, paginate GET /extractions/{id}, or normalize direct tweets[] pages.

Queue or data lake

Write normalized rows to xquik-tweet-search.jsonl.

Cost control

Set resultsLimit on both estimate and create calls.

Live monitoring

Create an account or keyword monitor with signed webhooks.
Last modified on June 6, 2026