Brand alerts, financial research, and competitive dashboards usually need the same primitive: keyword search over public X posts, returned as JSON you can log, dedupe, and ship to Slack without running a headless browser.
Social Fetch exposes GET /v1/twitter/search for that job. Pass a query string, optional filters, engagement floors, and a cursor for the next page. Every response uses the same { data, meta } envelope as the rest of the API, with meta.requestId on every call. Two credits per completed lookup. Charge on completed lookup: HTTP 200 with zero tweets still bills; lookup_failed and HTTP 503 do not. Same auth header and envelope as TikTok, YouTube, Reddit, and Instagram. Full parameter list in the API reference.
Why DIY X search breaks
Rolling your own X search works in a notebook. In production it turns into maintenance.
Search pages expect a logged-in or guest session with valid cookies and CSRF tokens. Tokens expire. The cron that worked Tuesday can return an empty DOM on Wednesday.
X ships UI changes without a changelog. The article selectors and __NEXT_DATA__ blobs you parsed last month move or shrink. Silent partial HTML is worse than a hard error: your dashboard shows zero mentions while a browser shows plenty.
Residential proxies, fingerprint rotation, and backoff logic eat engineering time. Success rates drop when a subnet gets flagged. You still pay for the proxy round trip when the page loads a challenge instead of results.
Infinite scroll on the web does not map cleanly to page two. Cursor tokens are opaque, short-lived, and tied to the search context. Replaying them from a stale session fails in ways that look like "no more results."
DIY also means your IP addresses hit X directly. You own logging, retention, and incident response when a scrape breaks during a demo.
A data API does not remove your obligations around lawful use of public data. It moves session handling, upstream breakage, and normalized output to infrastructure that is supposed to be boring.
What GET /v1/twitter/search gives you
Pass a query string and optional filters. The endpoint supports the operators users expect from the native search box: OR, quoted phrases, negation with -.
section accepts top, latest, people, photos, or videos. Use latest for crisis watches and hourly polls; use top for weekly recap dashboards. Engagement floors (minLikes, minRetweets, minReplies) drop low-signal noise before your warehouse insert. startDate and endDate use YYYY-MM-DD; language (for example en) narrows the corpus for sentiment work.
Successful responses match every other Social Fetch route:
The people array fills when section=people. For tweet sections, expect tweets in data.tweets.
Log meta.requestId and meta.creditsCharged on every poll. When a customer asks why Tuesday's alert missed a post, you want a support trail, not a guess about proxy health.
Pagination and billing
Responses include data.page.nextCursor and data.page.hasMore. Pass the cursor back as the cursor query parameter on the next request. Do not invent scroll tokens. Use exactly what the previous response returned.
Search costs 2 credits per completed lookup. Confirm on every response via meta.creditsCharged.
That follows the charge-on-completed-lookup rule documented in Credits: we bill when the upstream fetch completes and we return HTTP 200. Search routes do not expose lookupStatus the way profile lookups do, but the billing shape is the same. An empty data.tweets array still means the lookup ran and bills.
| Outcome | Charged? |
|---|---|
| Pre-send validation error (bad query format, invalid cursor) | No |
lookup_failed / HTTP 503 | No |
HTTP 200 with zero tweets in data.tweets | Yes (completed lookup) |
| HTTP 200 with tweets returned | Yes |
Empty results still cost credits because the upstream search still ran. That matches DIY scraping too: you paid for the proxy round trip when the page loaded but the index had nothing new. Here the cost shows up as prepaid credits with a requestId, not a mystery AWS line item.
Retry lookup_failed and HTTP 503 with exponential backoff. Those outcomes are not charged. Do not retry validation errors. Fix the query.
For high-volume polling, model credits before you turn on aggressive cadences: keywords × polls_per_day × 2 credits. Three brand terms polled hourly on X alone is about 144 credits per day before pagination.
Cron polling pattern
Most search integrations are cron jobs: load watch terms, call the API, upsert new posts, alert on spikes. Keep audit metadata on every run.
Tune minLikes per watch group. Crisis terms can run with no floor; brand terms can use a higher bar.
Store requestId on poll_runs, not only on individual mentions. You will need it when reconciling credit burn against finance. Dedupe on post ID, not poll timestamp. The same tweet can match multiple watch terms. Paginate until hasMore is false or your credit budget stops you. Deep pagination multiplies the 2-credit cost per poll. Split cadence by severity: crisis terms every 5–15 minutes, brand terms hourly or daily. Alert fatigue is a product bug. Fan out per watch term (QStash, a queue, or one serverless invocation per term) so a slow Reddit poll does not block your X crisis watch.
For a full multi-platform listening stack (schema, spike detection, troubleshooting), see Build a Social Listening Dashboard.
Official X API vs Social Fetch
Use the official X API when you need write access (posting, replying, DMs, OAuth on behalf of users), when your volume fits a published tier and you accept X's rate limits, or when compliance or procurement requires a first-party vendor relationship.
Use Social Fetch when you need read-only search JSON without negotiating enterprise contracts: keyword alerts, brand monitoring, and research dashboards that poll public posts, with the same auth header and envelope you already use for TikTok, YouTube, Reddit, and Instagram.
We are not claiming parity with every X API tier or every private field behind login. Check route coverage in the API reference before you design around an endpoint. When an official route exists and is affordable for your volume, use it. This guide is for the gap where browser-parity search matters and first-party pricing does not. For the pricing fork (official X meter vs public-data credits), see Twitter / X API pricing.
Do not ship keys to clients
API keys use the sfk_ prefix and travel in the x-api-key header. Call Social Fetch from your backend, edge worker, or cron, not from a browser bundle.
Get started
If you need a Twitter keyword search API you can call from a backend cron or a live product feature, start here:
- API reference for parameters and response shapes
- Quickstart for auth and the success envelope
- Playground to try queries in the browser
- Pricing to model volume
New accounts get 100 free credits. Run your watch list for a week, log success rate and credit burn, then decide whether to keep DIY on life support or ship the boring API path.