Twitter API Benchmark: Latency and Reliability, 600 Calls
A first-party Twitter/X API benchmark: 600 live calls across six read endpoints, per-endpoint p50 and p95 latency, a 100% success rate, and the script to reproduce it.

TL;DR: On 2026-09-19 we made 600 sequential live calls to the GetXAPI read API, 100 each across six endpoints. All 600 returned HTTP 200. Median response time, measured as time to first byte on an open connection, ran from 0.83s (trends) to 2.01s (advanced search), and five of the six endpoints had a median under 2 seconds. Full round trips from the test client in India, opening a fresh connection every call, had medians from 1.28s to 2.79s. The raw method and a script to rerun it are below. Cost is covered in the cost benchmark.
The results
600 calls, six read endpoints, 100 calls each, run one after another between 05
and 06 UTC on 2026-09-19.| Endpoint | Calls | HTTP 200 | Response p50 | Response p95 | Total p50 | Total p95 | Avg payload |
|---|---|---|---|---|---|---|---|
trends |
100 | 100% | 0.83s | 2.57s | 1.28s | 3.53s | 9 kB |
user/info |
100 | 100% | 1.20s | 1.74s | 1.60s | 2.27s | 1 kB |
user/tweets |
100 | 100% | 1.33s | 2.35s | 2.18s | 3.72s | 33 kB |
user/mentions |
100 | 100% | 1.40s | 2.23s | 2.06s | 3.46s | 28 kB |
user/followers |
100 | 100% | 1.61s | 2.62s | 2.79s | 5.86s | 92 kB |
tweet/advanced_search |
100 | 100% | 2.01s | 2.89s | 2.68s | 3.97s | 29 kB |
| All calls | 600 | 100% | 1.40s | 2.46s |
Response is the time from sending the request to receiving the first byte, on a connection that is already open. Total is the full wall time of a cold call: DNS, TCP, TLS, the response wait and the download.
Three things to read off the table:
- Five of six endpoints have a median response under 2 seconds. Across all 600 calls, 495 (82.5%) responded in under 2 seconds.
- Advanced search is the slow one. Its median sits at 2.01s and half of its calls came in over 2 seconds. It matches and ranks before returning, which is more work than a lookup.
- Payload size drives the gap between response and total.
user/inforeturns 1 kB and adds almost nothing after the first byte.user/followersreturns about 92 kB per page and spent a median 0.61s downloading it to the test client.
What the two numbers mean
Every call has a part the API controls and a part it does not, and folding them together hides which one you can change.
| Component | Median in this run | Who controls it |
|---|---|---|
| DNS lookup | 0.003s | Your resolver |
| TCP connect | 0.20s | Distance between client and API |
| TLS handshake | 0.21s | Distance, paid once per connection |
| Response wait | 0.83s to 2.01s by endpoint | The API and the endpoint you choose |
| Download | 0.00s to 0.61s by payload | Payload size and your bandwidth |
The test client was a residential connection in India, which is a long way from the API. Connection setup alone was a 0.41s median, and this benchmark paid it on all 600 calls because every call opened a fresh connection. That is the worst case on purpose. A real client that reuses connections, which requests.Session and every mainstream HTTP library do by default, pays the setup once and then sees something close to the response column plus the download. MDN's guide to HTTP connection management explains the mechanism.
The table reports p50 and p95 and leaves out the mean. Latency distributions are right-skewed, so a handful of slow calls pull an average above what most calls feel like. That is the problem Dean and Barroso describe in The Tail at Scale, and it is visible here: the single slowest call of the run was an 11.7 second trends call, on the endpoint with the fastest median.
Reliability: 600 of 600
All 600 calls returned HTTP 200. There were no 429 rate-limit responses and no 5xx errors across 23 minutes of continuous calls rotating through ten different accounts.
| Outcome | Count |
|---|---|
| HTTP 200 | 600 |
| HTTP 429 | 0 |
| HTTP 5xx | 0 |
| Timeouts (60s limit) | 0 |
This is one client in one session. It is evidence, not a service level agreement, and it does not cover time-of-day variation or other regions. Production code should still retry with backoff so a rare transient error does not end a long job:
import time, requests
def get_with_retry(url, headers, params, tries=4):
for i in range(tries):
r = requests.get(url, headers=headers, params=params, timeout=30)
if r.status_code == 429 or r.status_code >= 500:
time.sleep(2 ** i) # 1s, 2s, 4s, 8s
continue
r.raise_for_status()
return r.json()
r.raise_for_status()

Start building with GetXAPI
$0.05 per 1,000 tweets. $0.10 free credits. No credit card required.
Throughput
Sequential throughput on one connection is 60 divided by the median total time.
| Endpoint | Calls per minute, sequential | Items per call | Items per minute |
|---|---|---|---|
trends |
47 | up to 50 trends | n/a |
user/info |
37 | 1 profile | 37 profiles |
user/mentions |
29 | about 20 posts | about 580 posts |
user/tweets |
28 | about 20 posts | about 560 posts |
user/followers |
22 | 200 users | about 4,400 users |
tweet/advanced_search |
22 | about 20 posts | about 440 posts |
Those are floors, from a distant client paying connection setup on every call. Two levers raise them. Reusing the connection removes about 0.4s per call from this client. Running workers in parallel multiplies the figure, because there is no endpoint-specific quota to plan around. General service throttling still applies, so sustained concurrency can return 429, and the right worker count is the one just below where adding workers stops adding throughput. The rate limits guide covers the pacing side.
How we measured
- Client: one residential connection in India, a single machine, no VPN.
- Calls: 100 per endpoint, 600 in total, strictly sequential, interleaved across endpoints so no endpoint had a quiet or busy window to itself. No warmup calls discarded, no outliers removed.
- Inputs: ten public accounts rotated through (
nasa,github,vercel,stripe,nytimes,bbcworld,openai,spotify,nba,reuters) so the run was not the same request repeated. Search used the account name as the query withproduct=Latest. Trends usedcountry=US. - Timing:
curl -w, which reports DNS, connect, TLS, first byte and total separately. The body was discarded to/dev/nullso terminal rendering did not pollute the timing. Every call opened a new connection. - Billing: each call was billed at the standard $0.001, so the whole run cost $0.60.
- Percentiles: nearest-rank on the sorted sample.

Reproduce it
One timed call, with the timing split out:
curl -s -o /dev/null --max-time 60 \
-w "code=%{http_code} connect=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total}\n" \
-H "Authorization: Bearer $GETXAPI_KEY" \
"https://api.getxapi.com/twitter/user/info?userName=nasa"
Response time is first_byte minus tls. The full run:
import json, subprocess, os
KEY = os.environ["GETXAPI_KEY"]
USERS = ["nasa", "github", "vercel", "stripe", "nytimes",
"bbcworld", "openai", "spotify", "nba", "reuters"]
ENDPOINTS = {
"user/info": "twitter/user/info?userName={u}",
"user/tweets": "twitter/user/tweets?userName={u}",
"user/followers": "twitter/user/followers?userName={u}",
"advanced_search": "twitter/tweet/advanced_search?q={u}&product=Latest",
"user/mentions": "twitter/user/mentions?userName={u}",
"trends": "twitter/trends?country=US",
}
FMT = ('{"code":%{http_code},"tls":%{time_appconnect},'
'"ttfb":%{time_starttransfer},"total":%{time_total}}')
rows = []
for i in range(100): # N per endpoint
for name, path in ENDPOINTS.items():
url = "https://api.getxapi.com/" + path.format(u=USERS[i % len(USERS)])
out = subprocess.run(
["curl", "-s", "-o", "/dev/null", "-m", "60", "-w", FMT,
"-H", f"Authorization: Bearer {KEY}", url],
capture_output=True, text=True).stdout
rows.append({"ep": name, **json.loads(out)})
def pct(values, p):
values = sorted(values)
return values[min(len(values) - 1, int(len(values) * p))]
for name in ENDPOINTS:
r = [x for x in rows if x["ep"] == name]
resp = [x["ttfb"] - x["tls"] for x in r]
total = [x["total"] for x in r]
ok = sum(x["code"] == 200 for x in r)
print(f"{name:<16} ok={ok}/{len(r)} "
f"response p50={pct(resp, .5):.2f} p95={pct(resp, .95):.2f} "
f"total p50={pct(total, .5):.2f} p95={pct(total, .95):.2f}")
Run it from the machine your production code runs on. A published latency number, including every one in this post, was measured from someone else's network. Yours is the one that matters.
The cheapest Twitter API. Try it free.
$0.05 per 1,000 tweets. $0.10 free credits. No credit card required.
What this run does not show
- No other provider was measured. We hold no keys for other APIs, so there are no competitor numbers here. The one outside figure worth knowing is for a different delivery model: the official X Filtered Stream is reported at roughly five seconds of latency in an X developer community thread. A stream pushes matching posts continuously and suits always-on monitoring. A read API returns data when you ask and suits lookups, timelines, followers and scheduled search. The X developer docs describe the streaming model.
- One region, one session. No time-of-day spread and no second geography. A client near the API will see lower totals than these.
- Sequential only. This run characterises a single request. It says nothing about how latency holds as you add workers. To find that, run the same calls at 5, 10, 20 and 40 workers and look for where calls per minute stops rising.
- Read endpoints only. No write actions were timed.
Earlier run
The first version of this post, published 2026-06-13, reported 44 calls across four endpoints with medians between 2.7s and 4.4s on total time. This run replaces it: fourteen times the sample, two more endpoints, and the timing split into its components. On the four endpoints both runs covered, median total time is lower in this run on every one, from a client that is farther from the API.
| Endpoint | June run, total p50 (n=8 to 28) | This run, total p50 (n=100) |
|---|---|---|
user/info |
about 2.7s | 1.60s |
user/tweets |
3.3s | 2.18s |
user/followers |
4.0s | 2.79s |
tweet/advanced_search |
4.4s | 2.68s |
Choosing an endpoint by latency budget
| Workload | What matters | Reading from this run |
|---|---|---|
| Polling for new posts every 30s or more | Reliability, not per-call latency | A 1.3s to 2.0s response is a rounding error against the interval |
| Building a dataset | Throughput | Reuse connections, parallelise, checkpoint the cursor |
| AI agent calling the API as a tool | Median, since latency compounds per step | Prefer user/info and trends. Budget most for search |
| Blocking a page render on a live call | p95, not p50 | Cache, or move the call to a background job. p95 total reached 5.86s on followers |
The request patterns are in the Python tutorial. The paginated endpoints timed here are covered end to end in the followers export guide and the tweet history guide, and the production habits that sit on top of any API are in the best practices guide.
Frequently Asked Questions
In a first-party run of 600 calls on 2026-09-19, median response time, measured as time to first byte on an open connection, was 0.83 seconds for trends, 1.20 seconds for a profile lookup, 1.33 seconds for a user's tweets, 1.40 seconds for mentions, 1.61 seconds for a followers page and 2.01 seconds for advanced search. Five of the six endpoints had a median under 2 seconds, and 495 of the 600 calls, 82.5%, responded in under 2 seconds. Full round trips from the test client in India, on a fresh connection each time, had medians between 1.28 and 2.79 seconds.
In this run all 600 calls across six endpoints returned HTTP 200, with zero 429 rate-limit responses and zero 5xx errors over 23 minutes of continuous sequential calls. That is one client in one session, so it is evidence, not a service level agreement. Production code should still wrap calls in retries with exponential backoff.
Sequential single-connection throughput is 60 divided by the median total time. From the test client that was about 47 trends calls, 37 profile lookups, 29 mentions calls, 28 user-tweets calls, and 22 followers or advanced-search calls per minute. There is no endpoint-specific quota, so parallel workers raise that figure, though general service throttling still applies and sustained concurrency can return 429.
Yes. The test client was in India, where TCP and TLS setup took about 0.2 seconds each, and a 92 kB followers page took a median 0.61 seconds to download. A client closer to the API, or one that keeps connections open, will see lower total times than the ones published here. Run the script in this post from where your code runs to get your own figures.
Trends was fastest at a 0.83 second median response, followed by the profile lookup user/info at 1.20 seconds. Both return small payloads, about 9 kB and 1 kB. Advanced search was slowest at a 2.01 second median because it matches and ranks before returning, and the followers endpoint had the widest tail on total time because each page is about 92 kB and takes longer to download.
Because they answer different questions. Response time, the wait for the first byte once the connection is open, is mostly the work the API does. Total time adds DNS, TCP and TLS setup plus the download, which depend on where the client is and how big the payload is. From the test client in India, connection setup alone was a 0.41 second median per call. A client that reuses connections pays that once, not on every call.
No. Every latency and reliability number in this post is a first-party measurement of the GetXAPI production API. We hold no keys for other providers, so we publish no numbers for them. The one outside figure cited, roughly five seconds of latency on the official X Filtered Stream, comes from a thread in the X developer community and is labelled as cited.
Check out similar blogs
More guides on the Twitter/X API, scraping, and pricing.
Featured in
Where GetXAPI's data and pricing get cited.
















