All questionsX (Twitter)

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

GET /v1/twitter/profiles/@handle/posts
curl "https://api.openhandle.dev/v1/twitter/profiles/@copperfield_lab_x_test/posts" \
  -H "Authorization: Bearer $OPENHANDLE_API_KEY"
TypeScript SDK
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);
200 OK
{
  "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. /posts is the profile timeline: original posts and reposts, without replies.
  • Replies. /replies is the posts-and-replies tab. Read it too for a full picture of what the account wrote.
  • Media. /media is the media tab. Posts with images or video only.

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.

SituationStatusCode
The account is protected403PROFILE_PRIVATE
The account is suspended, deleted, or never existed404PROFILE_NOT_FOUND
The cursor came from another feed or freshness400CURSOR_MISMATCH
403 Forbidden
{
  "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.

For agents