Social Listening via X (Twitter) API — Build vs Buy
Social listening SaaS platforms — Brand24, Mention, Awario, Sprinklr, Meltwater — solve a real problem: continuously monitor brand + competitor + keyword mentions across social channels, alert on anomalies, aggregate sentiment. Their price ($200-500 per brand per month, or $2K+ for enterprise) reflects the operational overhead of running that monitoring stack.
For teams with in-house dev capacity and monitoring focused on X (Twitter) specifically, building the same core loop directly against the X API costs 5-100× less. Not because the SaaS platforms overcharge — they don't, given what they provide — but because you're skipping the multi-platform coverage, the pre-built dashboards, and the sentiment classifier they bundle in. If your workflow only needs X monitoring + custom alerts + integration into your existing stack, the build path is dramatically cheaper.
This page covers the build-vs-buy decision honestly: when SaaS wins, when API-build wins, and the exact API pattern + cost math if you go the build route.
Build vs buy — the honest tradeoff table
SaaS social listening bundles four things: (1) multi-platform monitoring, (2) pre-built dashboards + alerts, (3) sentiment / topic classification, (4) team collaboration features. If your workflow needs all four, buy is right — you're not saving money by rebuilding what a $500/mo tool ships out-of-box.
But if you need X-only + custom alert logic + integration into your existing analytics stack (Metabase / Grafana / Notion / Airtable / whatever), building on the X API skips 3 of the 4 SaaS layers and cuts cost 10-100×.
The 3-endpoint build pattern
The core social listening loop is: detect a mention → identify the author → measure reach → alert if criteria met. Three API calls cover it:
1. Detect — /twitter/tweet/advanced_search with query . Runs every 5-15 min (poll cadence). Returns matching tweets with tweet ID, text, timestamp, engagement counts.
2. Enrich — /twitter/user/info?userName= for each unique author in the batch. Returns follower_count, verified, bio. Enables filtering by author quality (e.g. skip low-follower spam).
3. Reach — sum of followers_count across all matching authors = brand reach for that poll cycle. Or use engagement (favorite_count + retweet_count) as engagement proxy.
Alert — if any (a) volume-per-hour spikes 3× baseline, (b) any single tweet accumulates >100 engagement in first 15min (viral signal), (c) any tweet from a specific author (competitor CEO, journalist watchlist) — fire your alert (Slack / email / PagerDuty).
Runnable — brand monitoring loop
One end-to-end script implementing the 3-endpoint pattern:
import os, requests, time, json
from pathlib import Path
from collections import defaultdict
from datetime import datetime, timezone, timedelta
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
BRAND = "stripe"
COMPETITORS = ["paypal", "square", "adyen"]
EXCLUDES = " ".join(f"-{c}" for c in COMPETITORS)
STATE_FILE = Path(f".state/{BRAND}_seen.json")
STATE_FILE.parent.mkdir(exist_ok=True)
def load_seen() -> set:
return set(json.loads(STATE_FILE.read_text())) if STATE_FILE.exists() else set()
def save_seen(s: set):
STATE_FILE.write_text(json.dumps(sorted(s)[-500:]))
def poll_once():
since = (datetime.now(timezone.utc) - timedelta(minutes=30)).strftime("%Y-%m-%d")
query = f"{BRAND} {EXCLUDES} lang:en -filter:retweets min_faves:5 since:{since}"
r = requests.get(f"{BASE}/twitter/tweet/advanced_search", headers=HEADERS, params={"query": query}, timeout=15)
r.raise_for_status()
tweets = r.json().get("tweets", [])
seen = load_seen()
new_tweets = [t for t in tweets if t["id"] not in seen]
if new_tweets:
# Reach proxy: sum followers of all new-mention authors
reach = sum((t.get("author", {}).get("followers_count") or 0) for t in new_tweets)
engagement = sum(t.get("favorite_count", 0) + t.get("retweet_count", 0) for t in new_tweets)
print(f" {len(new_tweets)} new · reach {reach:,} · engagement {engagement:,}")
# Alert criteria: high-reach single mention OR volume spike
for t in new_tweets:
author = t.get("author", {})
if author.get("followers_count", 0) > 50_000:
print(f" \U0001F6A8 HIGH-REACH MENTION: @{author.get('userName')} ({author.get('followers_count'):,} followers): {t.get('text', '')[:120]}")
if t.get("favorite_count", 0) + t.get("retweet_count", 0) > 100:
print(f" \U0001F525 VIRAL: {t.get('favorite_count')}\u2764 + {t.get('retweet_count')}\U0001F501: {t.get('text', '')[:120]}")
seen.update(t["id"] for t in new_tweets)
save_seen(seen)
while True:
try:
poll_once()
except Exception as e:
print(f" ERROR: {e}")
time.sleep(600) # 10-min poll · adjust per your alert latency needs
# Cost per twitterapi.io/pricing:
# ~50-200 tweets/poll x 144 polls/day = ~10-30K tweets/day = ~$1.50-4.50/day = ~$45-135/month per brandCost math at 4 monitoring volumes
Two observations: (a) at any volume the API-build wins on data cost; (b) SaaS pricing doesn't scale linearly with volume — they charge per-brand seat, so your delta stays large even at small volumes.
But: the SaaS bundles the dashboard + sentiment + alerts. Build-cost analysis must include eng time to build those layers. Rough parity: build wins if you already have 1 engineer + BI stack + volume >30K mentions/mo.
When to buy the SaaS (honest)
Multi-platform mandatory: You need LinkedIn + Instagram + Reddit + TikTok + X in one dashboard. Building all of that yourself against 5 different APIs is 5-10× the engineering time — the SaaS pricing looks cheap in comparison.
No engineering capacity: 5-person marketing team, no dev support, need it working today. Signup + import brand list in 1 hour vs 1 week to build MVP.
Regulated / compliance-sensitive: Some SaaS have SOC2 / GDPR / retention guarantees you'd otherwise implement in-house.
Turnkey sentiment / topic classification: The SaaS has trained sentiment classifiers per language + industry. Building your own is a project — either use OpenAI (add $0.01-0.05 per classified tweet) or accept lower quality VADER-style rule-based.
Cross-team collaboration UI: Marketers assigning mentions to different responders, tracking response SLA, generating shareable reports for exec review. SaaS ships this; you'd rebuild in Notion or similar.
When to build on twitterapi.io (honest)
X-only workflow: You only care about X (Twitter). 80%+ of dev-focused brands (SaaS, DevTools, crypto, APIs, cloud infra) live primarily on X. Skip the multi-platform tax you'd pay to SaaS.
Existing analytics stack: Data goes into your Metabase / Grafana / Looker / Notion / Airtable already. Adding X mentions as another data source in the same stack is 1 dev-day.
Custom alert logic: 'Alert only if a @
Cost sensitivity at scale: SaaS pricing tends to hard-cap at their enterprise tier and forces per-brand-seat expansion. Direct-API cost scales cleanly with actual tweet volume.
Data ownership: Every tweet lives in your database from the moment it's polled. No 'export CSV' friction, no SaaS-vendor-lock-in.
Sibling tools + comparison
Brand24 — mid-market SaaS, $99-499/mo, decent X coverage + sentiment. Best for teams that want an easy start.
Mention — similar to Brand24, slightly stronger on real-time alerting.
Awario — cheaper alternative, $29-249/mo, thinner on features but usable.
Sprinklr — enterprise-grade, $1K-10K+/mo, best for large teams with formal social-response workflows.
Meltwater — enterprise media monitoring including press/news alongside social. $5K+/mo.
twitterapi.io + your build — $5-500/mo depending on volume. No SaaS bundling; pure data + code you own. See /pricing for per-call rates.
None of these are strictly better — they solve different points on the price/capability curve. Choose based on team + workflow + budget, not vendor prestige.
# Full workflow: 5-brand watchlist + Slack alerts + Notion database sink.
import os, requests, time, json
from datetime import datetime, timezone, timedelta
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]
WATCHLIST = ["stripe", "paypal", "square", "adyen", "checkout"]
STATE_DIR = Path(".state"); STATE_DIR.mkdir(exist_ok=True)
def seen_file(brand): return STATE_DIR / f"{brand}_seen.json"
def load_seen(brand):
f = seen_file(brand)
return set(json.loads(f.read_text())) if f.exists() else set()
def save_seen(brand, s):
seen_file(brand).write_text(json.dumps(sorted(s)[-500:]))
def slack_alert(brand: str, tweet: dict, kind: str):
a = tweet.get("author", {})
txt = (tweet.get("text") or "").replace("\n", " ")[:200]
url = f"https://twitter.com/{a.get('userName')}/status/{tweet.get('id')}"
requests.post(SLACK_WEBHOOK, json={
"text": f"{kind} on **{brand}**: @{a.get('userName')} ({a.get('followers_count'):,} followers)\n{txt}\n{url}"
})
def poll_brand(brand: str) -> int:
since = (datetime.now(timezone.utc) - timedelta(minutes=15)).strftime("%Y-%m-%d")
query = f"{brand} lang:en -filter:retweets min_faves:5 since:{since}"
r = requests.get(f"{BASE}/twitter/tweet/advanced_search", headers=HEADERS, params={"query": query}, timeout=15)
r.raise_for_status()
tweets = r.json().get("tweets", [])
seen = load_seen(brand)
new_tweets = [t for t in tweets if t["id"] not in seen]
for t in new_tweets:
a = t.get("author", {})
if (a.get("followers_count") or 0) > 50_000:
slack_alert(brand, t, "\U0001F6A8 HIGH-REACH MENTION")
if t.get("favorite_count", 0) + t.get("retweet_count", 0) > 100:
slack_alert(brand, t, "\U0001F525 VIRAL MENTION")
seen.update(t["id"] for t in new_tweets)
save_seen(brand, seen)
return len(new_tweets)
while True:
with ThreadPoolExecutor(max_workers=5) as ex:
counts = list(ex.map(poll_brand, WATCHLIST))
print(f" {sum(counts)} new mentions across {len(WATCHLIST)} brands")
time.sleep(900) # 15-min poll cycle
# Cost estimate per twitterapi.io/pricing:
# ~50-200 new tweets/brand/poll x 5 brands x 96 polls/day = ~24-96K tweets/day = ~$3.60-14.40/day = ~$108-432/month total
# vs Brand24 for 5 brands = $500-1000/month (roughly 3-5x more)Questions readers ask
Which SaaS should I compare against as baseline?
For SMB: Brand24 ($99-499/mo) or Mention ($41-499/mo). For enterprise: Sprinklr ($1K+/mo) or Meltwater ($5K+/mo). All have decent X coverage; differences are in cross-platform depth + sentiment classifier + dashboard UX.
Can I build sentiment analysis on top of the API?
Yes — pipe the returned tweet text through your sentiment classifier of choice. Options: OpenAI (text-embedding-3-small for topic + gpt-4o-mini for sentiment, ~$0.01 per classified tweet), VADER (free but rule-based, English only), or Hugging Face open-source models (self-host).
How do I avoid missing tweets between polls?
Use since: operator + track already-seen tweet IDs (as the script does). Poll cadence of 10-15 minutes is standard for brand monitoring — tighter poll for crisis-response workflows. For sub-minute latency, use streaming API instead of polling.
Do I need X's Enterprise tier for historical data?
No — twitterapi.io exposes historical archive via /twitter/tweet/advanced_search with since:2020-01-01 until:2025-12-31 operators (or any window). Retroactive brand-mention research is 1 API call, no Enterprise contract needed.
What about GDPR / data-retention for stored mentions?
You control storage. Public tweet data is generally cleared for aggregation + research per X's Terms. For EU-user compliance, add a per-tweet TTL in your DB (typical: 90 days) or hash tweet IDs after aggregate metrics computed. If your workflow includes DM contents, that's a different compliance layer — public-tweet monitoring doesn't hit that.
How does this compare to X's official /2/tweets/search/all?
Same underlying data. X official /2/tweets/search/all (Full-Archive) is Enterprise-tier, contract-priced at ~$42K/month per docs.x.com/x-api/enterprise/getting-started. twitterapi.io's advanced_search covers the same historical archive at $0.00015/tweet with no tier gating.
Which is best for 'crisis response' (sub-5min alert latency)?
For sub-5min crisis alerting, use twitterapi.io streaming API (real-time push) instead of polling. See /blog/twitter-streaming-api-real-time-guide. SaaS platforms typically batch every 15-30 min, so build wins on latency for the crisis-response use case specifically.
Continue
- twitterapi.io — pricing
- X API — pricing (docs.x.com, 2026 verified)
- X — Enterprise API tier reference
- Brand24 pricing (competitor benchmark)
- Mention pricing (competitor benchmark)
- Twitter (X) API — cluster hub
- Twitter (X) API cost breakdown
- Twitter (X) advanced search API guide
- Twitter (X) monitoring — broader architecture patterns
- Twitter (X) keyword alerts — developer 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