# How do I get all posts from an X user past 3,200?

X (Twitter). Checked September 2026.

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.

## GET /v1/twitter/profiles/@handle/posts

```bash
curl "https://api.openhandle.dev/v1/twitter/profiles/@copperfield_lab_x_test/posts" \
  -H "Authorization: Bearer $OPENHANDLE_API_KEY"
```

```ts
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:

```json
{
  "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.

## 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` |

```json
{
  "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.

## Related

- [Can I get X posts by date range?](https://openhandle.dev/questions/can-i-get-x-posts-by-date-range): Bounding a feed by time with since and createdAt.
- [Pagination](https://openhandle.dev/docs/concepts/pagination): Opaque cursors, one page per request, and the since parameter.
- [X (Twitter) API](https://openhandle.dev/apis/twitter): Every X endpoint with examples.
