Key Takeaway: X search operators are keywords and symbols that filter tweets by author, date, engagement, media, language, and location. They turn a broad keyword search into a precise query, and more than 50 work on the web in 2026. The official X API v2 supports only a subset.
Updated July 2026: re-verified every operator against X's live search behavior and the official X API v2, refreshed Sorsa pricing to the current per-1,000 batch rates, and added the 100 free requests starting allowance. Earlier revisions added the frequently-confused-operators section, expanded the broken-operators reference, and added deep-pagination guidance.
Most cheat sheets quietly skip the part that matters most for real work: the highest-value operators are web-search operators that the official X API v2 does not support. min_faves:, min_retweets:, the rich since:/until: date syntax, within_time:, and filter:blue_verified all work in the x.com search box, and all are silently dropped by /2/tweets/search/recent. Sorsa API, an alternative Twitter/X API, passes the full web operator set straight through its Search Tweets endpoint, so every operator in this guide runs in production code, not just on the website. It bills per request instead of per resource, runs a flat 20 requests per second on every plan with no per-endpoint windows, and needs no developer-account approval, which is why operator-driven pipelines tend to leave the official API behind.
This guide is built for two readers: the marketer who wants copy-paste queries that just work, and the developer who needs to run those queries at scale. Every operator below is grouped by what it filters, with a working example, and the cookbook turns them into 14 ready-to-run query patterns.
For credit where it is due, this reference draws on real-world testing plus the community-maintained twitter-advanced-search reference by Igor Brigadir, the de facto industry source on undocumented X search behavior.
How X Search Operators Work
X search operators are small text commands you append to a query to filter the result set. They work in three places: the x.com search bar, TweetDeck, and any third-party API that passes the full web search syntax through, such as the Sorsa Search Tweets endpoint. The syntax is operator:value with no space around the colon, and operators can be combined freely.
Operators fall into two broad categories. Standalone operators can be used on their own (for example from:elonmusk returns a valid result set). Conjunction-required operators must appear alongside at least one standalone operator, because they would otherwise match too much content. This distinction matters more on the official X API v2 than on the web, but it is worth understanding from the start.
Three universal rules:
- AND is implicit. Putting two terms next to each other (
bitcoin etf) requires both. - OR must be uppercase. Lowercase
oris treated as a literal word. - Exclusion uses a leading dash.
crypto -scamremoves results containing "scam".
If you plan to use these in production, bookmark the Sorsa Search Builder. It is a free, no-login tool that lets you toggle filters visually and generates a copy-ready query string with full operator coverage. It is the fastest way to prototype a query before integrating it into code.
Web Operators vs Official X API v2 Operators
This is the single most important thing most cheat sheets do not tell you. The X advanced search syntax that works on x.com is a superset of the operator list supported by the official X API v2 search endpoint. If you build a production pipeline on /2/tweets/search/recent and pass it min_faves:100 since:2026-01-01 filter:blue_verified, none of those three operators do anything. They are not errors. They are silently dropped.
We have seen this exact bug in several migration projects since 2024. The query "works", in the sense that it returns tweets, but the filtering you thought you had is gone. By the time someone notices, the dashboard has been wrong for weeks.
Here is the operator-by-operator comparison for the ones developers actually care about:
| Operator (web syntax) | Works on x.com / Sorsa | Works on official X API v2 |
|---|---|---|
min_faves:N, min_retweets:N, min_replies:N | Yes | No (not supported at all) |
since:YYYY-MM-DD, until:YYYY-MM-DD | Yes | No (use start_time/end_time request params) |
within_time:Xd, since_id:, max_id: | Yes | No |
filter:blue_verified | Yes | No (only is:verified) |
filter:follows, filter:social | Yes (UI only) | No |
filter:has_engagement | Yes | No |
filter:images, filter:twimg, filter:videos, filter:native_video, filter:pro_video | Yes | Partial (only has:media, has:images, has:video_link) |
filter:spaces | Yes | No |
card_name:*, card_domain:, card_url: | Yes | No |
near:"city", within:Xkm, geocode: | Yes | Partial (only point_radius:, bounding_box:, place:, place_country:) |
source:client_name | Yes | No |
quoted_user_id: | Yes | No (only quotes_of_tweet_id:) |
filter:news, filter:safe | Yes | No |
Wildcard "word * word" | Yes | No |
from:, to:, @, #, $, url:, lang: | Yes | Yes |
is:retweet, is:reply, is:quote, is:verified | Yes (with slight naming differences) | Yes (these are the API v2 names) |
The biggest casualties for real work are the engagement filters (min_faves, min_retweets, min_replies) and the rich date syntax. Without min_faves:, you cannot efficiently surface viral or influential content on the API v2 side. You can pull tweets and filter client-side, but on high-volume queries you end up burning your quota on tweets you immediately discard, and the cost difference compounds fast.
That cost gap is concrete. The official X API v2 bills per resource: a single search returning 20 posts plus their author profiles costs about $0.30 (20 post reads at $0.005 plus 20 user reads at $0.010). The same call on Sorsa's Pro plan is one request at roughly $0.002, with each tweet's author profile included at no extra charge. The official X API v2 also imposes hard character limits on the query string itself, 512 characters for self-serve recent search, 1,024 for full-archive, and 4,096 only at the enterprise tier, while web syntax and Sorsa's pass-through are bounded only by the practical operator cap of around 22 to 23 operators per query. If you need to post or send DMs, the official API is still the tool for that; for reading and searching public data with the full operator set, a Twitter/X API alternative like Sorsa is the reason operator-driven search teams switch.
Disclosure: Sorsa is our product. We have kept this comparison strictly factual; the missing-operator list is verifiable against X's own public operator documentation on the day this article was revised. For a deeper look at the tradeoffs, see our migration guide from the official X API.
Keyword, Phrase, and Boolean Logic
These are the building blocks. Every advanced query starts here.
| Operator | What it matches | Example |
|---|---|---|
keyword keyword | Tweets containing both terms. Space acts as implicit AND. | nasa esa |
keyword OR keyword | Tweets containing either term. OR must be uppercase. | bitcoin OR ethereum |
"exact phrase" | Tweets containing the exact phrase in that order. Also prevents auto-correction. | "state of the art" |
-keyword | Excludes tweets containing the term. Works with phrases and other operators. | crypto -scam |
( ) | Groups terms for complex Boolean logic. | (AI OR "machine learning") lang:en |
"word * word" | Wildcard inside a quoted phrase. The * replaces any single word. | "this is the * time" |
+word | Forces exact match, preventing X's auto-correction and stemming. | +radiooooo |
#hashtag | Matches a specific hashtag. | #tgif |
$cashtag | Matches a stock or crypto symbol. | $TSLA |
A few practical notes that trip people up. Plurals match their singulars and vice versa: bulls will match bull. X sometimes silently re-interprets common words as content intent, so searching photo may return tweets with attached images even when the word "photo" is absent from the text; wrap such words in double quotes to force a literal match. Operators are not strictly bound to the tweet body either: they can match against the author's display name, screen name, and expanded URLs inside the tweet, which is a frequent source of surprising results.
The cap on operator count is real. Once you cross roughly 22 to 23 operators in a single query, X starts ignoring trailing parts of the string silently. If you need more than that, split into multiple API calls and merge results downstream.
User and Account Filters
These filter tweets by who posted, who they reply to, or who is mentioned.
| Operator | Description | Example |
|---|---|---|
from:username | Tweets sent by a specific account (without the @). | from:elonmusk |
to:username | Tweets that are replies to a specific account. | to:openai |
@username | Tweets that mention a specific account anywhere in the text. | @sorsa_app |
list:ID | Tweets from members of a public X List. Use the numeric List ID from the URL. | list:715919216927322112 |
filter:verified | Only from legacy verified accounts (pre-2023 blue checkmarks). | AI filter:verified |
filter:blue_verified | Only from X Premium (paid Blue) subscribers. | crypto filter:blue_verified |
filter:follows | Only from accounts you follow. UI only, cannot be negated. | filter:follows |
filter:social | From your algorithmically expanded network. Works on "Top" results, not "Latest". | filter:social |
Brand monitoring trick. Combine @ or a quoted brand name with -from: to find what everyone except the brand itself says about the brand: "Tesla" -from:tesla. That single move is the difference between actionable signal and PR noise, and it is the backbone of most social listening setups.
For a deeper treatment of mention monitoring, see the docs on tracking mentions; the list: operator pairs naturally with the X List API when you want every member's tweets in one feed.
Engagement Gating
Filter by minimum (or maximum) engagement. These are essential for cutting through noise and surfacing viral content, and they are also the operators most often missing from the official X API v2.
| Operator | Description | Example |
|---|---|---|
min_faves:N | Minimum number of likes. | AI min_faves:100 |
min_retweets:N | Minimum number of retweets. | crypto min_retweets:50 |
min_replies:N | Minimum number of replies. | "product launch" min_replies:20 |
-min_faves:N | Maximum likes (negated form). | bitcoin -min_faves:1000 |
-min_retweets:N | Maximum retweets. | news -min_retweets:500 |
-min_replies:N | Maximum replies. | tech -min_replies:100 |
filter:has_engagement | Tweets with at least one interaction. Can be negated to find zero-engagement tweets. | from:username filter:has_engagement |
How to set thresholds. Start low (min_faves:10) and increase iteratively. X reports become approximate above roughly 1,000, so do not over-tune. Combine with -filter:retweets if you only want tweets that earned engagement on their own content rather than through amplification. In our own pipeline work, the combination min_faves:N plus -filter:retweets plus -filter:replies is the single most useful filter for surfacing original viral content; everything else is dressing.
Media and Content Type Filters
X has unusually granular control over what kind of content appears in your results. The catch is that the web operator set is much richer than the API v2 equivalents.
Media filters
| Operator | Description |
|---|---|
filter:media | All media types (images, video, GIFs). |
filter:images | All images, including third-party links (e.g., Instagram). |
filter:twimg | Only native X images (pic.twitter.com links). |
filter:videos | All video types: native X video, YouTube embeds, and so on. |
filter:native_video | Only X-owned video (native uploads, legacy Vine, legacy Periscope). |
filter:consumer_video | X native video only (excludes pro/Amplify). |
filter:pro_video | X pro video (Amplify) only. |
filter:spaces | X Spaces audio content. |
filter:links | Tweets containing any URL. Includes media URLs; use -filter:media to isolate non-media links. |
card_name:animated_gif | Specifically matches GIFs. |
Tweet type filters
| Operator | Description |
|---|---|
filter:replies | Only tweets that are replies to another tweet. |
-filter:replies | Exclude replies (show only top-level original tweets). |
filter:nativeretweets | Only native retweets (created via the retweet button). |
include:nativeretweets | Include native retweets in results (they are excluded by default). |
filter:retweets | Old-style RT retweets plus quote tweets. |
-filter:retweets | Exclude retweets entirely. |
filter:quote | Only quote tweets. |
quoted_tweet_id:ID | Quotes of a specific tweet by its ID. |
quoted_user_id:ID | All quotes of a specific user by their user ID. |
conversation_id:ID | All tweets in a thread (direct replies and nested replies). |
Special content filters
| Operator | Description |
|---|---|
card_name:poll2choice_text_only | Tweets containing 2-choice text polls. |
card_name:poll3choice_text_only | 3-choice text polls. |
card_name:poll4choice_text_only | 4-choice text polls. |
card_name:poll2choice_image | 2-choice image polls. |
filter:news | Tweets linking to recognized news domains. |
filter:safe | Excludes NSFW or potentially sensitive content. Not a guarantee. |
filter:hashtags | Only tweets containing at least one hashtag. |
filter:mentions | Only tweets containing any @mention. |
Date, Time, and Snowflake IDs
Precise time-based filtering is critical for event analysis, campaign tracking, and historical data extraction. This is also where the official X API v2 diverges most sharply: it expects start_time and end_time as separate request parameters and does not understand since: / until: in the query string. Web syntax and Sorsa support the full set.
| Operator | Format | Description |
|---|---|---|
since:YYYY-MM-DD | since:2026-01-01 | Tweets posted on or after this date (inclusive). |
until:YYYY-MM-DD | until:2026-03-01 | Tweets posted before this date (not inclusive). |
since:YYYY-MM-DD_HH:MM:SS_UTC | since:2026-03-05_12:00:00_UTC | Precision timestamp with timezone. |
since_time:UNIX | since_time:1142974200 | After a specific Unix timestamp (in seconds). |
until_time:UNIX | until_time:1142974215 | Before a specific Unix timestamp. |
within_time:Xd | within_time:2d | Within the last X days. Also supports h (hours), m (minutes), s (seconds). |
since_id:ID | since_id:1234567890 | After a specific Snowflake ID (not inclusive). |
max_id:ID | max_id:1234567890 | At or before a specific Snowflake ID (inclusive). |
The Snowflake ID trick
Every tweet ID on X is a Snowflake ID that encodes its creation timestamp at millisecond precision. The conversion formula:
millisecond_epoch = (tweet_id >> 22) + 1288834974657
This is useful for two reasons. First, you can compute the exact post-time of any tweet without making an API call, which is handy for backfill jobs that dedupe or order by time. Second, since_id: and max_id: give you tweet-level rather than date-level boundaries on result windows, which is invaluable when you are paginating a high-volume keyword over hours and want to resume exactly where you left off without re-fetching tweets you have already seen.
For a deeper walkthrough of pulling historical tweet sets, see our guide on searching old tweets.
Geographical Filters
A reality check before you go deep here: only an estimated 1 to 2 percent of tweets carry precise geolocation data. X removed precise location tagging from the main iOS and Android apps in June 2019, and most users never opted in to begin with. Geo filters are still useful, but expect thin coverage.
| Operator | Description | Example |
|---|---|---|
near:"city" | Geotagged near a named place. Supports phrases. | near:"San Francisco" |
near:me | Near your current location (UI only). | near:me |
within:Xkm | Radius limit for near:. Accepts km or mi. | earthquake near:Tokyo within:50km |
geocode:lat,long,radius | Pinpoint precision using coordinates. | geocode:37.77,-122.41,5km |
place:ID | Search by X Place Object ID. | place:96683cc9126741d1 (USA) |
On the structured API side, the official X API v2 uses a different geo set, place_country:, point_radius:, and bounding_box:, in place of the web near:/within:/geocode: operators. Sorsa accepts the web geo operators through its query field, the same ones that work in the x.com search box; the API v2 forms are shown in the comparison table above.
A useful fallback behavior. If a tweet does not have precise coordinates, search falls back to reverse-geocoding the user's profile location, so you may receive tweets that match based on the author's stated location rather than the tweet's actual origin. That is sometimes what you want and sometimes confusing. For a higher-coverage approach to mapping where an audience is based, see audience geography by country.
Language and Source Filters
Language
X uses 2-letter ISO 639-1 codes: lang:en, lang:es, lang:fr, lang:de, lang:ja, lang:ru, and so on. There are also several non-standard codes worth knowing:
| Code | Meaning |
|---|---|
lang:und | Undefined language (emoji-only or media-only tweets). |
lang:qme | Tweets with media links only (since 2022). |
lang:qst | Very short text tweets. |
lang:qht | Tweets with hashtags only. |
lang:qam | Tweets with mentions only. |
lang:qct | Tweets with cashtags only. |
lang:zxx | Tweets with media or a Twitter Card only, no additional text. |
One high-signal use: from:user lang:zxx filter:images returns tweets that are an image and nothing else, with zero text noise. X's language detection is not perfect, though. Short tweets, code snippets, and emoji-heavy posts are routinely misclassified, so for critical applications run your own language detection on the body text after retrieval.
Source (posting client)
| Operator | Description | Example |
|---|---|---|
source:client_name | Filter by the app used to post. Use underscores for spaces. | source:Twitter_for_iPhone |
Common values: Twitter_for_iPhone, Twitter_for_Android, Twitter_Web_App, TweetDeck, twitter_ads. Note that source: sometimes needs another operator alongside it to return results.
Card and URL Operators
These match on Twitter Card metadata: the rich previews attached to tweets containing links, media, and embedded content. Two things to know up front: card_name: typically only works for tweets from the last 7 to 8 days, and url: works well for domains but is unreliable for long URL paths.
| Operator | Description |
|---|---|
card_domain:domain | Matches the domain name in a Twitter Card. Mostly equivalent to url:. |
card_url:domain | Similar to card_domain: but may return different results. |
card_name:audio | Tweets with Player Cards (Spotify, SoundCloud, and so on). |
card_name:player | Tweets with any Player Card. |
card_name:summary | Small-image summary cards. |
card_name:summary_large_image | Large-image summary cards. |
card_name:promo_website | Promoted website cards (usually posted via Ads). |
card_name:promo_image_convo | Conversational ad cards with images. |
card_name:promo_video_convo | Conversational ad cards with video. |
url:domain | Matches URLs. Works well for domains and subdomains. Hyphens must be replaced with underscores (e.g., url:t_mobile.com). |
Operators People Mix Up
A handful of operators look interchangeable and are not. These are the pairs that quietly corrupt a dataset, so it is worth being precise about each one.
filter:verified vs filter:blue_verified. filter:verified matches accounts that held legacy verification (journalists, public figures, organizations verified before 2023). filter:blue_verified matches anyone subscribed to paid X Premium. Most brand-monitoring and editorial queries want filter:verified for signal, not filter:blue_verified, which includes any paying user. To isolate legacy accounts cleanly, combine them: filter:verified -filter:blue_verified.
-filter:retweets vs include:nativeretweets vs -is:retweet. -filter:retweets (web syntax) excludes both old-style "RT" text retweets and native retweets. include:nativeretweets adds native retweets back into a result set that excludes them by default. -is:retweet is the official X API v2 spelling for excluding retweets, and it is narrower than filter:retweets, which historically also swept in quote tweets. For a clean set of original content on the web side, use -filter:retweets; to track how far one tweet spread, use filter:nativeretweets with a tight time window.
within_time:Xd vs since:/until:. within_time:7d is a rolling window measured from the moment the query runs, so the same query returns a different tweet set tomorrow than it does today. since: and until: are fixed calendar boundaries. For reproducible research datasets, always prefer explicit since:/until: dates over within_time:.
from:user vs @user. from:user returns only tweets authored by that account. @user returns any tweet mentioning the account, including replies and quote tweets from other people. Use from: for timeline analysis and @ for mention monitoring; on common-word handles, add lang:en or a small engagement floor to @ queries to cut noise.
filter:retweets vs -is:retweet. filter:retweets is web syntax that matches retweets; -is:retweet is the API v2 syntax for excluding them. They are not perfect inverses, so to exclude every form of amplification on the web side, pair -filter:retweets with -filter:quote.
These operators filter tweets by interaction type. Retrieving the actual replies, quotes, and retweeters behind a given tweet is a separate job, handled by dedicated endpoints and covered in the Twitter engagement API guide.
Cookbook: 14 Production-Ready Recipes
Operators are useful in isolation. They are powerful in combination. Here are fourteen query patterns we have either built ourselves or seen in client pipelines. Copy them, swap the variables, and paste them straight into the X search bar or the Sorsa search endpoint.
1. Brand and reputation monitoring
Find original viral content about a brand, excluding the brand's own posts and retweet noise:
("Tesla" OR "Elon Musk") min_faves:500 filter:links lang:en -from:tesla -filter:nativeretweets
2. Competitor lead generation
Find users actively asking about alternatives in your niche:
("notion" OR "obsidian") "?" -filter:links -from:notionhq lang:en
3. High-intent buyer discovery
Find tweets that read like buying signals for a product category:
("looking for" OR "anyone use" OR "recommend") ("twitter api" OR "x api") -filter:retweets lang:en
4. Influencer discovery
High-engagement original posts from verified accounts in a topic:
"machine learning" filter:blue_verified min_faves:200 -filter:replies -filter:retweets lang:en
5. OSINT and breaking news
Track real-time events with visual evidence from verified sources:
"breaking news" filter:images filter:blue_verified within_time:6h
6. Content curation from X Lists
Find viral videos posted by members of a specific List:
list:715919216927322112 (filter:videos OR card_name:animated_gif) min_retweets:50
7. Developer troubleshooting
Find error-related conversations linking to GitHub:
url:github.com "error" lang:en filter:replies
8. Crypto sentiment with engagement gating
Track sentiment-laden conversation about a token, filtered for substance:
(bitcoin OR $BTC) (bullish OR bearish OR crash OR moon) min_faves:20 lang:en since:2026-01-01 -filter:retweets
9. Hyper-local monitoring
What is being said near a specific place in a tight time window:
"traffic" near:"London" within:5km since:2026-03-05_12:00:00_UTC
10. Find quote tweets of a specific user
Pattern-match the URL form and exclude the user's own handle:
twitter.com/elonmusk/status/ -from:elonmusk
11. Original-only thread leaders
Find tweets that started threads (not replies, not retweets) and earned real engagement:
"your topic" min_replies:10 -filter:replies -filter:retweets lang:en
12. Track a product launch window
Capture all conversation in a specific date range with an engagement floor:
"product name" since:2026-02-10 until:2026-02-17 lang:en min_faves:5
13. Zero-engagement spam detection
Identify suspicious low-quality posting (useful for moderation pipelines):
"buy now" -filter:has_engagement filter:links lang:en
14. Job board mining
Hiring-signal tweets in a specific technical niche:
("hiring" OR "we're looking for") ("react" OR "typescript") -filter:retweets lang:en min_faves:5
The pattern across all fourteen: start with the topic, layer engagement, layer content type, then layer exclusions. The exclusions are usually what separates a noisy result set from a usable one.
Using Operators with the Sorsa API
Every operator listed above works in the query field of the Sorsa /v3/search-tweets endpoint. Pass your full query string in the body of a POST request, paginate via next_cursor, and handle 429s with a brief retry. For the wider workflow around ordering, pagination, and result handling, the guide to searching tweets via API walks through it end to end.
A minimal call with curl:
curl -X POST https://api.sorsa.io/v3/search-tweets \
-H "ApiKey: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "(AI OR \"machine learning\") min_faves:100 lang:en -filter:retweets",
"order": "popular"
}'
Python: production-ready with pagination and retry
This is the pattern we run in production. It paginates the full result set, retries on rate limiting, and surfaces hard errors:
import requests
import time
from typing import Iterator
API_KEY = "YOUR_SORSA_API_KEY"
BASE_URL = "https://api.sorsa.io/v3/search-tweets"
def search_tweets(query: str, order: str = "latest") -> Iterator[dict]:
"""
Paginate through every tweet matching the query.
Retries on 429 (rate limit) with a 1-second wait.
"""
cursor = None
while True:
payload = {"query": query, "order": order}
if cursor:
payload["next_cursor"] = cursor
response = requests.post(
BASE_URL,
headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
json=payload,
timeout=30,
)
if response.status_code == 429:
time.sleep(1.0)
continue
response.raise_for_status()
data = response.json()
for tweet in data.get("tweets", []):
yield tweet
cursor = data.get("next_cursor")
if not cursor:
break
# Usage: collect viral AI tweets from January 2026
for tweet in search_tweets(
'(AI OR "machine learning") min_faves:1000 lang:en '
'since:2026-01-01 until:2026-02-01'
):
print(tweet["id"], tweet["likes_count"], tweet["full_text"][:80])
JavaScript / Node.js: async iterator pattern
const API_KEY = "YOUR_SORSA_API_KEY";
const BASE_URL = "https://api.sorsa.io/v3/search-tweets";
async function* searchTweets(query, order = "latest") {
let cursor = null;
while (true) {
const payload = { query, order };
if (cursor) payload.next_cursor = cursor;
const res = await fetch(BASE_URL, {
method: "POST",
headers: { ApiKey: API_KEY, "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (res.status === 429) {
await new Promise((r) => setTimeout(r, 1000));
continue;
}
if (!res.ok) throw new Error(`Sorsa API error: ${res.status}`);
const data = await res.json();
for (const tweet of data.tweets ?? []) yield tweet;
cursor = data.next_cursor;
if (!cursor) break;
}
}
// Usage
for await (const tweet of searchTweets(
'"product launch" min_faves:50 lang:en since:2026-02-10'
)) {
console.log(tweet.id, tweet.likes_count);
}
Deep pagination is unreliable: chunk by date instead
One thing to plan for on any high-volume historical pull: X's search pagination is unstable for deep result sets. This is an upstream platform behavior that every access path inherits, not a quirk of one API. Past roughly the first dozen pages of a single cursor chain, you start seeing duplicates or the chain stops early, well before the result set is exhausted.
The fix is to stop relying on one long cursor chain and split the query into date-range chunks instead. Run several smaller queries, each bounded by since: and until:, and paginate each chunk on its own fresh cursor:
from datetime import date, timedelta
def chunked_search(query_base: str, start: date, end: date, chunk_days: int = 7):
"""Split a long date range into weekly chunks, each with its own cursor chain."""
current = start
while current < end:
chunk_end = min(current + timedelta(days=chunk_days), end)
full_query = (
f"{query_base} since:{current.isoformat()} until:{chunk_end.isoformat()}"
)
yield from search_tweets(full_query, order="latest")
current = chunk_end
# Q1 2026, week by week, no deep-cursor instability
for tweet in chunked_search(
'openai min_faves:200 lang:en', date(2026, 1, 1), date(2026, 4, 1)
):
print(tweet["id"])
For fast-moving events where even a week is too wide, drop to hourly chunks using the full timestamp form (since:2026-03-01_12:00:00_UTC until:2026-03-01_13:00:00_UTC). Each chunk is reproducible and resumable, which matters when you are reconstructing the timeline of a launch or a news event. For archival pipelines that need to snapshot specific tweets rather than search them, the tweet-info-bulk endpoint takes up to 100 tweet IDs per request.
Building Complex Queries: Order of Operations
Once you start stacking five or six operators, the order they are evaluated in starts to matter. The rule on X is the same as on most search engines: AND binds tighter than OR.
That means cat OR black dog is evaluated as cat OR (black dog), not (cat OR black) dog. If you want the second interpretation, parenthesize: (cat OR black) dog. When in doubt, use parentheses. They cost you nothing and they eliminate ambiguity.
A construction order that works for almost every query:
- Group core keywords in parentheses:
(bitcoin OR ethereum OR $BTC) - Add content constraints:
lang:en,filter:images,-filter:replies - Set engagement thresholds:
min_faves:50,min_retweets:10 - Exclude noise:
-from:spambot,-scam,-airdrop,-filter:retweets - Add time bounds if needed:
since:2026-01-01 until:2026-03-01
Follow this order consistently and you can read any of your queries at a glance and spot mistakes faster.
What Is Broken or Unreliable in 2026
Operators fail quietly on X. The query still returns tweets, so a broken filter looks like a working one until the data is already wrong. These are the failure modes worth knowing before they bite.
Operators that no longer behave as their names suggest:
| Operator | Status in 2026 | Why |
|---|---|---|
filter:vine | Historical only | Vine shut down in 2017; matches only archived pre-2017 content. |
filter:periscope | Historical only | Periscope shut down in 2021. |
near:, within:, geocode: | Reduced coverage | Precise geotagging was removed from the iOS and Android apps in June 2019; only 1 to 2 percent of tweets carry coordinates. |
filter:nativeretweets | Roughly 7 to 10 days | X retains native-retweet data only short-term. |
card_name:*, card_domain: | Roughly 7 to 8 days | Card metadata has short retention. |
filter:verified | Inconsistent | Legacy verification and paid Blue were conflated after the 2023 rebrand; use filter:verified -filter:blue_verified to isolate legacy accounts. |
Common "my search is not working" situations and what is actually happening:
- You are on "Top" instead of "Latest". The default Top tab shows an algorithmic selection and hides most matches, which reads like missing results. Switch to the Latest tab, or pass
order: "latest"on the API, for complete coverage. - An exact-phrase search in quotes returns nothing. Quotes force an exact token match and disable spell-correction, so a phrase that X has no exact match for comes back empty. Remove the quotes, or use the wildcard form
"word * word", to loosen it. from:returns nothing or garbage. The most common cause is a space after the colon: writefrom:username, neverfrom: username, since the space breaks the operator. The second most common cause is a date range during which the account did not post.geocode:ornear:returns almost nothing. Geo coverage collapsed after 2019; for location work, lean on profile-location fallback or analyze where an audience is based by country rather than tweet-level coordinates.- The query worked on x.com but not on the official X API v2. Almost always a web-only operator the API silently drops; see the web versus API v2 comparison table above.
A few more durable gotchas:
- Operator cap: queries support roughly 22 to 23 operators. Cross that and the trailing part of the query is silently ignored.
- Private and suspended accounts are excluded from all search results; no operator combination reaches them.
- Not all tweets are indexed. Posts flagged for platform or anti-spam reasons are excluded from search even when technically still live. This is a known gap when chasing engagement-blocked accounts (see our writeup on the Twitter "this request looks like it might be automated" error for related context).
- Auto-correction happens silently in some cases; use
+wordor"word"to force exact matching. - URL matching is fragile. Domains and subdomains work, long URL paths do not, and hyphens in domains must be replaced with underscores (
url:t_mobile.com).
In practice
A roughly 12-person social-analytics team we worked with had built a brand-monitoring dashboard on the official X API v2. Their query used min_faves: and filter:blue_verified to surface only high-signal mentions worth a human reply. On the API v2, both of those are web-only operators that get silently dropped, so for weeks the "top mentions" panel was ingesting every low-engagement mention and the prioritization was effectively random. Nobody saw an error, because there was none. Moving the same query string to a search API that accepts the full web operator set fixed it without rewriting any filter logic, and because the billing is per request rather than per resource, the same monitoring volume cost a small fraction of the per-post-read official pricing. The failure was invisible precisely because the operators that broke were the ones the official API never supported in the first place.
FAQ
What is X advanced search?
X advanced search is the platform's built-in way to filter tweets by author, date, engagement, media type, language, and location. It is available as a form at x.com/search-advanced, or you can type the same operators directly into the search bar from anywhere. Once you know the syntax, typing operators is faster than filling in the form.
How do I search Twitter by date?
To search Twitter by date, combine since:YYYY-MM-DD and until:YYYY-MM-DD in one query, for example "product launch" since:2026-02-10 until:2026-02-17. The since: date is inclusive and the until: date is exclusive, so the tweet must be posted before the until date, not on it. For sub-day precision, use the timestamp form since:2026-02-10_14:00:00_UTC.
Why isn't my search operator working on the official X API?
Operators like min_faves:, min_retweets:, since:, until:, within_time:, filter:blue_verified, and card_name: are web-search operators that the official X API v2 does not support; it silently ignores them instead of returning an error. Sorsa's search endpoint accepts the full web operator set, which is why teams running engagement-filtered or date-bounded pipelines move off the official API.
How do I find old tweets without an X account?
X requires login for most search in 2026, including the basic search bar. Two options work without your own account: the Internet Archive's Wayback Machine for specific tweet URLs you already have, or a third-party Twitter/X API that maintains its own access to the public search index, such as Sorsa, which returns historical results as structured JSON.
What's the difference between filter:retweets and -is:retweet?
filter:retweets is web-search syntax that matches retweets, while -is:retweet is the official X API v2 syntax for excluding them. They are not exact inverses: filter:retweets historically includes both old-style "RT" retweets and quote tweets, whereas the API v2 is:retweet is narrower. To exclude every form of amplification on the web side, use -filter:retweets -filter:quote together.
How many search operators can I combine in one query?
X starts silently ignoring operators after roughly 22 to 23 in a single query, so the trailing part of an over-long query is dropped without an error. The official X API v2 also caps the query string itself at 512 characters for self-serve recent search, 1,024 for full-archive, and 4,096 only at the enterprise tier.
Is there a Twitter/X API that supports the full set of search operators?
Yes. The official X API v2 supports only a subset of search operators, but Sorsa's Search Tweets endpoint passes the full web operator set through, including min_faves:, since:/until:, and filter:blue_verified. It runs on a flat 20 requests per second on every plan with no per-endpoint windows and no developer-account approval, and returns each tweet's author profile at no extra cost.
Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.
Sources and How We Checked This
This guide draws on our hands-on work building and running an alternative Twitter/X API (more than 5 billion requests served since 2022), tested against our live Search Tweets endpoint, plus the community-maintained twitter-advanced-search reference by Igor Brigadir and the official X API v2 operator documentation. Every operator listed here was re-checked against X's current search behavior in June 2026, and the web-versus-API-v2 differences were verified against X's own published operator list on the day of this revision. The operator reference also lives in the Sorsa docs if you want it alongside the endpoint reference.
Getting Started
The fastest way to put this cheat sheet to work:
- Open the Search Builder and assemble a query visually. No login, and no rate limit on building.
- Run it in the Sorsa Playground to see live results with JSON and CSV export.
- When you are ready to script it, drop your query into the Python or JavaScript example above and call the search endpoint with your API key. Every account starts with 100 free requests: one-time, no card required, valid across all 40 endpoints, and enough for up to 10,000 tweets or 20,000 profiles. The quickstart walks through key creation if you have not done that yet.
Coming from the official X API v2 and tired of operators that silently do nothing? The migration guide maps the differences endpoint by endpoint, and on the batch endpoints Sorsa works out to from $0.02 per 1,000 tweets and from $0.01 per 1,000 profiles, on a flat 20 requests-per-second rate limit with no approval queue. Full pricing is public.