How do I get all posts from an X user past 3,200?
The 3,200 limit is a rule of the official X API user timeline. Openhandle pages GET /v1/twitter/profiles/@handle/posts as far as X’s public profile timeline goes, one page per request, with cursors that keep working. For older posts, search with from:handle and a keyword reaches what X’s search index still holds.
Neither path is a complete archive. X decides how far back a public timeline and its search index go. Openhandle returns what X shows now and never claims more.
Checked September 2026 · request and response run against the API · no affiliate links
curl "https://api.openhandle.dev/v1/twitter/profiles/@copperfield_lab_x_test/posts" \
-H "Authorization: Bearer $OPENHANDLE_API_KEY"import { OpenHandle } from '@openhandle/sdk';
const openhandle = new OpenHandle({ apiKey: process.env.OPENHANDLE_API_KEY! });
let page = await openhandle.twitter.profile('copperfield_lab_x_test').posts.list();
let count = 0;
while (page) {
count += page.data.length;
page = await page.next(); // null when X shows no more
}
console.log(count);{
"platform": "twitter",
"resource": "post",
"capturedAt": "2026-09-18T12:28:09Z",
"source": "live",
"data": [
{
"id": "940100000000000001",
"text": "A deterministic text post from a fictional lab. #synthetic",
"createdAt": "2026-08-09T15:30:00Z",
"metrics": { "likes": 42, "reposts": 3, "comments": 3 }
}
],
"meta": { "cursors": { "next": "b3BhcXVlLWN1cnNvcg" } }
}Trimmed to one post. `meta.cursors.next` is null on the last page. The example is a Test account with four posts, so you can test the loop on a free Test key.
Three feeds, one account
- —Posts.
/postsis the profile timeline: original posts and reposts, without replies. - —Replies.
/repliesis the posts-and-replies tab. Read it too for a full picture of what the account wrote. - —Media.
/mediais the media tab. Posts with images or video only.
Reach older posts with search
Call GET /v1/twitter/search/posts?q=from:handle keyword&sort=latest. X’s search index reaches further back than the profile timeline for many accounts, but it is a search, not a list. Vary the keyword to cover more ground. Store every post id so overlapping searches do not double count.
Keep it from happening again
The reliable way past any cap is to never fall behind. Poll the profile posts endpoint on a schedule with since set to your last capture time, store every post, and your own database becomes the archive. Pagination stops at since, so you never pay for pages you already have.
When this does not work
These answers are definitive. Store them, do not retry them.
| Situation | Status | Code |
|---|---|---|
| The account is protected | 403 | PROFILE_PRIVATE |
| The account is suspended, deleted, or never existed | 404 | PROFILE_NOT_FOUND |
| The cursor came from another feed or freshness | 400 | CURSOR_MISMATCH |
{
"error": {
"code": "PROFILE_PRIVATE",
"message": "This profile is private.",
"requestId": "req_01j8…",
"retryable": false
}
}Every page bills as one answered request, including the last, shorter one. An account that went protected mid-way answers PROFILE_PRIVATE on the next page. Store what you have.
Read next
More X (Twitter) questions
Send your agent ahead.
Paste the prompt into your agent and it sets everything up. Or come yourself, it takes five minutes.