Pagination
Cursor-based pagination across search, list, and follower-graph endpoints, with a copy-paste loop that reads every page.
List-style endpoints return one page at a time. To read the rest, you follow a cursor. This applies to search, follower-graph, and list endpoints, which is everywhere a response can hold more rows than fit in a single call.
How it works
Each page response carries two pagination fields:
| Field | Type | Description |
|---|---|---|
has_next_page | boolean | true when more results exist. false on the last page. |
next_cursor | string | An opaque token. Pass it as the cursor parameter to fetch the next page. Empty string on the final page. |
To advance, take next_cursor from the response and send it back as the cursor query parameter on your next request. Repeat until has_next_page is false.
# First page: no cursor.
curl "https://api.twitterapis.com/tweet/advanced_search?query=from%3Anaval" \
-H "Authorization: Bearer $TWITTERAPIS_KEY"
# Next page: pass the cursor from the previous response.
curl "https://api.twitterapis.com/tweet/advanced_search?query=from%3Anaval&cursor=DAABCgABF..." \
-H "Authorization: Bearer $TWITTERAPIS_KEY"Reading every page
A short loop reads the full result set. Keep calling until has_next_page is false, carrying the cursor forward each time.
async function readAll(query) {
const all = [];
let cursor = "";
do {
const url = new URL("https://api.twitterapis.com/tweet/advanced_search");
url.searchParams.set("query", query);
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },
});
const page = await res.json();
all.push(...page.tweets);
cursor = page.next_cursor;
// Loop while the server says there is more.
if (!page.has_next_page) break;
} while (cursor);
return all;
}import os
import requests
def read_all(query):
all_tweets = []
cursor = ""
while True:
params = {"query": query}
if cursor:
params["cursor"] = cursor
res = requests.get(
"https://api.twitterapis.com/tweet/advanced_search",
headers={"Authorization": f"Bearer {os.environ['TWITTERAPIS_KEY']}"},
params=params,
)
page = res.json()
all_tweets.extend(page["tweets"])
if not page["has_next_page"]:
break
cursor = page["next_cursor"]
return all_tweetsTreat the cursor as opaque
Do not parse, edit, or store assumptions about the cursor string. It is a server token. Pass back exactly what you received. Page size is fixed per endpoint, so there is no page-size parameter to tune.
A note on cost
Each page is one billed call. A query that spans ten pages costs ten standard calls. Stop paging as soon as you have what you need rather than draining the full result set out of habit.