Note: For a fuller walkthrough with a method comparison table, a CSV export pipeline, and additional code examples, see Historical Twitter Data: How to Search Old Tweets via API on the blog.
Endpoints
/search-tweets accepts the full X search operator set, including since:, until:, from:, to:, min_faves:, min_retweets:, lang:, and filter: directives, passed inline in the query field. /user-tweets takes only an account identifier (user_link, username, or user_id) and returns that account’s full timeline, with no query filtering.
Keyword Archive Search
Use/search-tweets when you need every tweet matching a query within a date window, across all users. Pass the date-bounded query in the JSON body:
order accepts "latest" (chronological) or "popular" (engagement-ranked). For date-bounded archive collection use "latest"; for content research, "popular" surfaces the highest-engagement posts first.
Full Account Timeline
Use/user-tweets when you want the complete posting history of one account, from newest to oldest, without a 3,200-tweet cap.
user_link, username, or user_id. Paginate with next_cursor until it returns null; the endpoint walks the timeline in reverse chronological order.
To pull one account’s tweets within a specific date range, use /search-tweets with the from: operator instead (for example, from:naval since:2020-01-01 until:2021-01-01). /user-tweets does not accept date filters.
What You Can Retrieve
Every historical tweet returns with the same field set as a recent one:- Full text (no truncation, no URL replacement)
- All six engagement metrics:
likes_count,retweet_count,reply_count,quote_count,view_count,bookmark_count - Embedded
userobject with the author’s full profile entitiesarray with media URLs (photos, videos, GIFs) and link previews- Conversation metadata:
conversation_id_str,in_reply_to_tweet_id,is_reply,is_quote_status - Language tag (
lang)
Platform-Level Limits
These are X-side restrictions, not Sorsa-specific. No public API can work around them.- Deleted tweets are removed from X’s search index and cannot be retrieved.
- Protected accounts are excluded from all public search and timeline results.
- Profile snapshots are not historical. A tweet from 2014 returns the author’s current bio, username, and follower count, not the 2014 values.
- Engagement metrics are not snapshots. Like, retweet, and view counts reflect current totals, not the counts as they stood on a specific past date. If you need point-in-time engagement, ingest tweets in real time via Real-Time Monitoring and store the metrics yourself.
Best Practices
Chunk Large Date Ranges
A single query across a multi-year window has no clean retry path and no per-period auditability. Split by month for year-scale collections, by week for volatile event windows.Filter Retweet Noise
Historical popular searches return waves of native retweets that bury original content. Add-filter:nativeretweets for sentiment, opinion, or content-pattern research. Use -filter:retweets to also exclude legacy RT @user: retweets.
Pair Engagement and Date Filters
Combiningsince: / until: with min_faves: or min_retweets: cuts noise and request volume sharply. Example:
Split Global Topics by Language
For worldwide events, separate queries perlang: give cleaner per-locale datasets than mixing languages.
Paginate Until the Cursor Is Empty
Terminate only whennext_cursor is null, empty, or absent. Don’t stop early on small page sizes. Full pattern in Pagination.
Related
- Search Tweets: endpoint reference for
/search-tweets - Search Operators: full operator dictionary
- Pagination: cursor-based pagination details
- Real-Time Monitoring: pair with historical backfill for forward-looking ingestion
- Track Mentions: historical mention tracking for any handle
- Optimizing API Usage: reduce request count on large collections