Searching X by Date: Why Your Range Returns Less Than It Should
Searching X by Date: Why Your Range Returns Less Than It Should
The operators are two words long and look self-explanatory:
from:nasa since:2026-01-01 until:2026-06-30
Then you run it, get 40 results for a six-month window, and reasonably conclude the account went quiet. It didn't. ★You hit a result cap, not the end of the data.★
This is the single most misunderstood behaviour in X search, and it silently corrupts any analysis built on date ranges.
The two operators
| Operator | Meaning | Boundary |
|---|---|---|
since:YYYY-MM-DD |
On or after this date | Inclusive |
until:YYYY-MM-DD |
Before this date | ★Exclusive★ |
⚠️ until: does not include its own date. until:2026-06-30 stops at the end of 29 June. To include the 30th, write until:2026-07-01.
This asymmetry costs people a day at every boundary. If you're sweeping month by month, an off-by-one here means twelve missing days a year, appearing as a mysterious dip in your data rather than an obvious error. (Every post comes back with its own timestamp, so filtering locally sidesteps the boundary question entirely.)
They work independently. since: alone means "from then to now". until: alone means "from the beginning to then".
The timezone question
Dates are interpreted in UTC, not your local time.
For most searches this doesn't matter. It matters a great deal when you're measuring something time-sensitive — a launch, an incident, a market event — because a post made at 8pm in California on the 15th is already the 16th in UTC.
★If you're in a timezone far from UTC and slicing by day, your "day" and X's "day" are different windows.★ For precise work, widen the range by a day on each side and filter locally on the actual timestamps, which come back on every post.
Why narrow windows return more than wide ones
This is the counter-intuitive part, and it's the reason most date-range analysis is quietly wrong.
Each query returns a bounded number of results. It stops when it hits that bound, not when it has exhausted your date range. A six-month window doesn't return six months of posts — it returns whatever the cap allows, taken from one end of the range.
The practical consequence:
one query: since:2026-01-01 until:2026-07-01 → ~40 results
six queries: month by month over the same span → ~240 results
★Same period, six times the data, purely from splitting the query.★
⚠️ This is why "the account went quiet in March" is usually a measurement artefact. Before concluding anything about a gap in your data, re-run that specific period as its own narrow query. The gap almost always fills in.
How narrow? Depends on posting volume. A quiet account is fine month by month. A prolific account or a busy keyword needs weekly or even daily windows. The rule of thumb: ★if a window returns close to the cap, it's truncated — split it and run again.★
Sweeping a long period without gaps
The correct pattern is chunking, and the correct chunk size is "small enough that no chunk hits the cap":
import requests
from datetime import date, timedelta
BASE = "https://api.socialapi.tech"
KEY = "your_api_key"
HDRS = {"X-API-Key": KEY}
def search(query, limit=100):
r = requests.get(f"{BASE}/v1/search/advanced",
params={"query": query, "product": "Latest", "limit": limit},
headers=HDRS, timeout=60)
r.raise_for_status()
return r.json()["data"]
def sweep(base_query, start, end, days=7):
"""Walk a date range in chunks, splitting any chunk that looks truncated."""
seen, out = set(), []
cursor_date = start
while cursor_date < end:
chunk_end = min(cursor_date + timedelta(days=days), end)
q = f"{base_query} since:{cursor_date} until:{chunk_end}"
batch = search(q)
# a full-looking batch probably means we were cut off
if len(batch) >= 95 and days > 1:
half = max(days // 2, 1)
out.extend(sweep(base_query, cursor_date, chunk_end, days=half))
else:
for post in batch:
if post["id"] not in seen:
seen.add(post["id"])
out.append(post)
cursor_date = chunk_end
return out
posts = sweep("from:nasa", date(2026, 1, 1), date(2026, 7, 1), days=30)
print(f"{len(posts)} posts")
if posts:
dates = sorted(p["created_at"] for p in posts)
print(f"from {dates[0]} to {dates[-1]}")
The adaptive split is the important bit. A fixed chunk size either wastes calls on quiet periods or truncates on busy ones. Splitting only when a chunk comes back full gets you completeness without paying for it everywhere — and call count is what drives cost.
Deduplicate anyway. Chunk boundaries and cap behaviour both produce overlaps. Paging and dedup work the same way across every endpoint.
What date search genuinely can't do
Separating measurement artefacts from real limits:
Old content thins out. Search leans heavily toward recent posts. Several years back, a date range returns partial results no matter how narrow you make it — the index doesn't hold it. Chunking fixes truncation; it can't fix absence.
Deleted posts are gone. No date range recovers them. See what actually works for old posts.
No time-of-day operator. since:/until: take dates, not timestamps. To slice by hour, fetch the day and filter on created_at locally.
★The honest summary: date search is reliable for recent periods and increasingly unreliable the further back you go. If you need dependable history, collect forward rather than reconstructing backward.★
Questions people ask
How do I search tweets by date?
Add since:YYYY-MM-DD and until:YYYY-MM-DD to your query. Remember until: is exclusive.
Why does my date search return so few results? Almost certainly the result cap, not an empty period. Split the range into smaller windows and re-run.
Is until: inclusive?
No. It stops before that date. Add a day to include it.
What timezone does Twitter search use? UTC. If you're far from UTC and slicing by day, widen the range and filter locally.
How do I search a single day?
since:2026-05-01 until:2026-05-02.
How far back can I search by date? Nominally to the start; practically, results thin out quickly with age. Recent months are dependable.
Can I search by time of day? Not with operators. Fetch the day and filter on the timestamps you get back.
How do I find my own tweets from a specific period?
from:yourusername since: until:. For genuinely old posts your downloaded archive is more complete.
Why do I get different results running the same date query twice? Search has some variability, and which slice of a truncated range you receive isn't guaranteed stable. Another reason to chunk and deduplicate.
Can I combine date search with other operators?
Yes, all of them — from:, min_faves:, filter: and the rest. See the full operator set.
How do I search a date range on mobile? Type the operators into the normal search box. The advanced search form isn't in the app, but the syntax works.
What's the date format?
YYYY-MM-DD. Other formats fail silently or get ignored, which looks like the operator not working.
Can I search before Twitter existed? Dates before 2006 return nothing, unsurprisingly.
How do I find the first tweet on a topic?
Set a wide until: and work backwards in chunks. Bounded by how far the index reaches, so treat the result as "earliest findable" rather than "first".
Does date search work without an account? Logged-out search is heavily restricted in general — see what works logged out.
Why is my date range returning newer posts than requested?
Usually a format error causing the operator to be ignored. Check for YYYY-MM-DD and no stray spaces around the colon.
How do I export tweets from a date range? Sweep the range in chunks as above, deduplicate, and write out the results.
Can I search deleted tweets by date? No. Deletion removes them from the index entirely.
What's the maximum results per query? Bounded per query, which is exactly why chunking matters more than any single limit number.
How do I monitor a date range going forward? You don't — for future content you want monitoring rather than search. Date ranges are for looking back.
Why do results differ between Latest and Top? Different ranking and, in practice, different result sets. Latest for completeness, Top for prominence.
How do I find tweets by date?
Combine since: and until: with your terms. ★Both take YYYY-MM-DD★ and the range is exclusive at the end.
How do I find tweets from a certain date?
Set since: to that day and until: to the next. ★A one-day window needs two dates, not one.★
How do I sort tweets by date? Use the Latest tab — ★Top reorders by prominence, which silently breaks chronological reading★.
How do I search before a date?
until:YYYY-MM-DD alone bounds the top end and leaves the start open.
Why does a date range return so little? ★Search does not reach far back reliably★ — the limit is archive depth, not your query. What actually reaches back.
How do I find tweets by date?
since: and until: with your terms — ★both take YYYY-MM-DD★.
How do I look for tweets by date? Same operators. ★Bracket the day you want, using the next day as the upper bound.★
How do I check tweets from a certain date?
A one-day window needs two dates — ★since: that day, until: the next★.
How do I view tweets from a certain date? Same query, read in the Latest tab — ★Top reorders and breaks chronology★.
How do I search before a date?
until:YYYY-MM-DD alone bounds the top and leaves the start open.
What is the date format?
★YYYY-MM-DD★ — other formats fail silently rather than erroring.
How do I search a date range? Both operators together — ★the upper bound is exclusive★, which is the off-by-one people hit.
How do I sort posts by date? Use Latest. ★There is no separate sort control★ — the tab is the sort.
Can I combine dates with an account?
Yes — from:username since:… until:… — searching within one account.
Is there a tweet finder by date? The operators are the finder. ★Tools with that name build the same query string.★
Can I search bookmarks by date? Bookmarks are private to you — ★no external tool reaches them★.
Why do dates seem to be ignored? ★Usually the format, or the range sits below search's horizon★ — test the query without dates first.
If you're doing period analysis
The failure mode to design against isn't an error message — it's ★silent truncation that looks like genuine data★. A quarter that returns 40 posts looks plausible. Nothing warns you that it should have been 400.
Two rules cover most of it: chunk small enough that no window returns a full batch, and treat any full batch as evidence you were cut off.
Our API takes the same operator syntax with cursor-based paging on top, so a chunk that does have more available can be paged rather than re-split. Read-only, flat price per call, no rate limit of your own to manage.
Related reading: every operator that still works · finding genuinely old posts · monitoring going forward instead.