Twitter (X) API — Search Hashtags Tutorial
Searching hashtags via API is one of the simplest advanced-search patterns and one of the most common. Brand campaigns, event tracking, trend research, community-management workflows — all of them start with 'get me every tweet using #tag'.
This tutorial walks the exact API call with runnable Python, the useful filter combinations, and the honest cost per provider. Pricing references URL-cited.
The basic hashtag search — three parameters
Query: #hashtag — that's the whole operator. Case-insensitive. Combine with other operators separated by spaces (AND is implicit).
Language filter (optional but useful): #tag lang:en — English-only. Prevents your English-language monitor from being drowned by, say, K-pop fan chatter.
Engagement floor (optional but useful): #tag min_faves:50 — only tweets with 50+ likes. Filters out spam / low-signal noise.
Date range (optional): #tag since:2024-01-01 until:2024-12-31 — bounded window. Note until: is UTC-exclusive; add a day for inclusive semantics.
Path 1 — twitterapi.io advanced_search
Auth via X-API-Key. Cursor pagination to 100K+ results per query.
Pricing per twitterapi.io/pricing: $0.00015 per returned tweet. A hashtag pulling 500 tweets/day = $0.075/day = ~$2.25/month for continuous monitoring.
import os, requests
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
def search_hashtag(tag: str, lang: str = "en", min_faves: int = 0, max_pages: int = 10):
"""Search tweets containing #tag with optional filters."""
query = f"#{tag}"
if lang: query += f" lang:{lang}"
if min_faves > 0: query += f" min_faves:{min_faves}"
tweets, cursor = [], None
for _ in range(max_pages):
params = {"query": query}
if cursor: params["cursor"] = cursor
r = requests.get(
f"{BASE}/twitter/tweet/advanced_search",
headers=HEADERS, params=params, timeout=15,
)
r.raise_for_status()
resp = r.json()
tweets.extend(resp.get("tweets", []))
cursor = resp.get("next_cursor")
if not cursor: break
return tweets
# Example: high-signal #machinelearning tweets
for t in search_hashtag("machinelearning", lang="en", min_faves=100)[:5]:
print(f" @{t.get('author', {}).get('userName')}: {t.get('text', '')[:80]}")
print(f" -> {t.get('public_metrics', {}).get('like_count')} likes")Path 2 — X official recent-search
Same query syntax. Auth via bearer token from X Developer Console. Recent-search covers last 7 days; older date ranges require Enterprise /2/tweets/search/all.
Pricing per docs.x.com/x-api/getting-started/pricing: $0.005 per post read.
# pip install tweepy
import tweepy
client = tweepy.Client(bearer_token="YOUR_X_BEARER")
def search_hashtag_x(tag: str, min_faves: int = 0, max_results: int = 100):
query = f"#{tag}"
if min_faves > 0: query += f" min_faves:{min_faves}"
tweets = []
for page in tweepy.Paginator(
client.search_recent_tweets, query=query,
tweet_fields=["public_metrics", "created_at", "author_id"],
max_results=max_results, limit=10,
):
tweets.extend(page.data or [])
return tweets
for t in search_hashtag_x("machinelearning", min_faves=100)[:5]:
print(f" {t.public_metrics['like_count']} likes: {t.text[:80]}")Common hashtag-search patterns
Live campaign monitoring — poll #your-campaign-tag every 5 min, alert on volume spikes or negative-sentiment matches.
Event tracking — #EventName since:CONFERENCE_START until:CONFERENCE_END for a full conference archive. Perfect for post-event content curation.
Trend research — #tag since:MONTH-AGO min_faves:1000 to find breakthrough moments; useful for content-marketing hindsight.
Community management — #your-community-tag -is:retweet for original-post tracking (excluding amplification retweets).
Cross-hashtag intersection — #tag1 #tag2 for tweets using both. Useful for niche-community mapping.
Exclusion — #brand -#brand-competitor to filter out competitive-mention noise.
Side-by-side — 2 paths for hashtag search
Costs derived from each provider's published pricing pages.
Two practical observations: (a) the 33× per-call cost ratio makes twitterapi.io the default for any sustained hashtag-monitoring product; (b) the full-archive depth matters for retrospective research (looking back at past campaigns or events).
What can go wrong — three gotchas
Case sensitivity is not what you'd expect: hashtags are matched case-insensitively, so #AI and #ai and #Ai all match. Don't run three separate queries thinking they'll return different results.
Special characters break silently: #c++ and #f# don't work as hashtags on X — the platform strips at the special character. If you're monitoring a tech-adjacent hashtag with symbols, monitor the plain-alphanumeric substring.
Non-Latin scripts are supported but you need proper URL encoding: #人工知能 works but must be URL-encoded in the query parameter. Most HTTP clients handle this automatically; if you see empty results for a non-Latin hashtag, check your client's encoding.
Picking the path
Building a hashtag-monitoring product / campaign dashboard → twitterapi.io. Cheap per call + full-archive depth for historical context.
One-off recent search of a hashtag → either works; X official if already authenticated.
Long-tail archive research on historical hashtags → twitterapi.io (full-archive) or X Enterprise (also full-archive but enterprise-priced).
# Practical example: continuous hashtag monitor with rolling window + alert threshold.
import os, requests, json
from datetime import datetime, timezone
from collections import Counter
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
TAG = "YourBrand"
MIN_FAVES = 5
SPIKE_THRESHOLD = 100 # tweets in last hour to trigger alert
def monitor_tag_last_hour(tag: str):
tweets, cursor = [], None
for _ in range(10):
params = {"query": f"#{tag} within_time:1h lang:en"}
if cursor: params["cursor"] = cursor
r = requests.get(f"{BASE}/twitter/tweet/advanced_search", headers=HEADERS, params=params, timeout=15)
r.raise_for_status()
resp = r.json()
tweets.extend(resp.get("tweets", []))
cursor = resp.get("next_cursor")
if not cursor: break
if len(tweets) >= SPIKE_THRESHOLD:
# Alert: volume spike
top_authors = Counter(t.get("author", {}).get("userName", "") for t in tweets).most_common(5)
print(f"🚨 #{tag} SPIKE — {len(tweets)} tweets in last hour")
print(f" top voices: {[a for a, _ in top_authors]}")
else:
print(f"#{tag} normal: {len(tweets)} tweets in last hour")
return tweets
result = monitor_tag_last_hour(TAG)
# Cost per twitterapi.io/pricing:
# Hourly poll × 24h × $0.00015 × ~50 tweets/poll = $0.18/day
# ~$5.40/month for continuous hashtag monitoring with alert threshold
# X official equivalent: ~$180/month (33x)Questions readers ask
Can I search multiple hashtags at once?
Yes — #tag1 #tag2 finds tweets containing BOTH (implicit AND). Use #tag1 OR #tag2 for either. Group with parentheses: (#a OR #b) #c for boolean precedence. Same operator set as X's advanced-search UI.
How do I get only original tweets, not retweets?
Add -is:retweet to your query: #tag lang:en -is:retweet. For only-retweets: #tag is:retweet. Both operators work across twitterapi.io and X official APIs.
What about tweets that just mention the hashtag as text but don't tag it?
The #hashtag operator matches only when the platform's parser identified the string as a hashtag entity (linked, part of tweet metadata). Plain text mentions of 'the hashtag #tag' where the # was escaped or the entity wasn't parsed don't match. To include mention-of-hashtag prose, add the plain word too: #tag OR "tag".
Can I get engagement metrics along with the tweets?
Yes — the response includes public_metrics per tweet (like_count, retweet_count, reply_count, quote_count). Filter by these client-side or use the min_faves: / min_retweets: / min_replies: operators server-side.
How do I follow a hashtag in real time (not polled)?
Use twitterapi.io's /oapi/tweet_filter/add_rule webhook: register #hashtag as the rule value, provide a callback URL. Matching tweets get pushed to your endpoint in near-real-time. See /blog/twitter-firehose-api-developer-guide for the streaming pattern.
Are hashtag counts the same as trending 'tweet volume' numbers?
Related but not identical. Trending tweet-volume is the algorithm's estimate for the trending list; hashtag search returns actual tweet counts you can pull. Search counts are more precise; trending volumes are indicative + cover a slightly different window.
Continue
- Twitter (X) API — cluster hub
- Twitter (X) hashtag analytics API guide
- Twitter (X) hashtag tracker tools API guide
- Twitter (X) advanced search — complete guide
- twitterapi.io pricing
Stop reading. Start building.
Starter credits cover real testing on real data. Google sign-in, no card, no application queue.
Get an API key