Use X Keyword Search with Mention & Reply Operators with Python
Search X (Twitter) by keyword with filters for date, language, engagement, media, verification, mentioned handle, author, reply target, and conversation thread, plus Top/Latest sort.
1. Choose the data you need
Review the published README for supported collection modes, examples, and limits. The recipe below uses the current published input definition.
2. Prepare a source-based input
This JSON contains published prefills and required-field defaults. Review every value for your task before running it; it is not a promise of successful collection.
{
"excludeReplies": false,
"excludeRetweets": false,
"keywords": [
"apify"
],
"language": "Any language",
"maxItems": 3,
"mode": "search",
"onlyImages": false,
"onlyQuotes": false,
"onlyVerifiedUsers": false,
"onlyVideos": false,
"sort": "Latest"
}
Download input.example.json and save your reviewed copy as input.json.
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | required | Search by keyword, collect an author's posts, fetch specific post URLs, or open a conversation thread. |
keywords | array | optional | Words, phrases or hashtags to search for. Each keyword is collected separately and every row shows the keyword that found it (searchTerm). |
authorHandles | array | optional | Used by the 'Posts by author' mode. Accepts @handle, handle, or https://x.com/handle profile URLs. |
postUrls | array | optional | Used by the 'Specific post URLs' mode. Accepts x.com or twitter.com post links and bare post IDs. |
conversationId | string | optional | Used by the 'Conversation thread' mode. Paste the root post ID or a post URL in that thread. |
maxItems | integer | optional | Stop after this many posts per keyword or author. The URL and conversation modes use it as a total cap. |
sort | string | optional | Latest is newest first. Top is ordered by likes and reposts. Top + Latest returns the top half by engagement, then the newest remaining posts. |
language | string | optional | Only keep posts in this language. The default searches every language. |
dateFrom | string | optional | Only keep posts published on or after this date (UTC). |
dateTo | string | optional | Only keep posts published on or before this date (UTC). |
excludeRetweets | boolean | optional | Drop reposts and keep original posts only. |
excludeReplies | boolean | optional | Drop replies and keep top-level posts only. |
onlyVerifiedUsers | boolean | optional | Keep posts from verified or blue-check accounts only. |
onlyImages | boolean | optional | Keep posts that contain at least one photo. |
onlyVideos | boolean | optional | Keep posts that contain at least one video or GIF. |
onlyQuotes | boolean | optional | Keep posts that quote another post. |
minimumLikes | integer | optional | Drop posts below this like count. Posts whose count is unavailable are dropped and reported in the run summary. |
minimumRetweets | integer | optional | Drop posts below this repost count. Counts are filled from the public fallback source when available. |
minimumReplies | integer | optional | Drop posts below this reply count. Posts with no available reply count are dropped and reported. |
mentioning | string | optional | Only keep posts that mention this handle (with or without @). Applied after collection. |
author | string | optional | Only keep posts written by this handle (with or without @). |
inReplyTo | string | optional | Only keep posts that are replies to this handle (with or without @). |
proxyConfiguration | object | optional | Optional. No proxy is needed. If supplied, it is used for the best-effort guest search supplement as well as page requests. |
3. Start an Actor run
Set APIFY_TOKEN in your environment. Python 3.10 or newer is sufficient; this recipe uses no third-party packages.
Execution may incur charges. Review current pricing on Apify. The request asks for a 120-second timeout and a charge limit; these settings are subject to Apify’s pricing and do not guarantee an all-inclusive spending cap.
import json
import os
import urllib.request
# Save the schema-derived example as input.json; review and edit it first.
with open("input.json", encoding="utf-8") as stream:
actor_input = json.load(stream)
token = os.environ["APIFY_TOKEN"]
request = urllib.request.Request(
"https://api.apify.com/v2/acts/xgRc7Nc7IkbNcF3bC/runs?timeout=120&maxTotalChargeUsd=0.50",
data=json.dumps(actor_input).encode("utf-8"),
headers={"Authorization": "Bearer " + token, "Content-Type": "application/json"},
method="POST",
)
# This starts a potentially billable run. Do not automatically retry this POST.
with urllib.request.urlopen(request, timeout=40) as response:
run = json.load(response)["data"]
print("Run ID:", run["id"])
print("Status:", run["status"])
# Inspect and download results in Apify Console once the run succeeds.
4. Inspect the actual results
Open the run in Apify Console and wait for a successful completion. Use the published output schema to locate results and the dataset schema to understand declared views. Missing or optional record fields must not be treated as guaranteed values.
X posts with full text, author profile, engagement counters, media, quoted post and reply context. Empty runs write a RUN_SUMMARY to the key-value store instead of a status row.
Questions before you run
Which inputs are required?
The published required fields are mode
What does this guide verify?
The fields, prefills, and schema links are rendered from the published build. This is a usage recipe, not a paid live extraction test. Source availability and collection results can vary.
What if the run request times out?
Check Apify Console before retrying. The first request may already have created a run. Do not automatically repeat a run-creation POST.
Generated from source build I7cduHm9oKbw9FGRa and its README and schemas. Source changes regenerate this guide; no third-party editorial claims are inferred.