# How do I get all the tweets from a Twitter account?

> Collect an X (Twitter) account's posts: page its timeline newest first, then reach older periods with from: and date-sliced search. Costs, code and limits.

Canonical page: https://okdata.online/answers/get-all-tweets-from-account/

**Short answer: **Page the account with X account posts ($0.006 per page of about 20 posts, newest first), and reach older periods with X post search using from:handle plus since:/until: dates ($0.006 per page). A year of an account that posts ten times a day is about 183 pages, roughly $1.098.

Say you want everything a competitor posted on X this year, to see what they announced and what landed. Two calls cover it. [X account posts](/apis/x/users/posts/list/) gives the account's posts newest first, a page at a time, and you stop when you pass your start date. For older stretches, or to be sure nothing was skipped, [X post search](/apis/x/posts/search/) with `from:handle` and a date window goes back period by period.

## Plan the run

Check the profile first with [X account profile](/apis/x/users/get/) ($0.001). Its `posts` field is X's own total for the account. That total includes replies and reposts, so your collected count will rarely match it exactly, but it tells you whether you are dealing with 400 posts or 40,000.

| Account | Posts | Pages | Cost |
|---|---|---|---|
| Posts 2 a day, one year | about 730 | 37 | $0.222 |
| Posts 10 a day, one year | about 3,650 | 183 | $1.098 |
| Same, sliced by month through search | about 3,650 | 183 | $1.098 |

## Code: timeline until a cut-off date

```python
import os, requests

API = "https://api.okdata.online/v1"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
START = "2026-01-01"

def get(path, **params):
    body = requests.get(f"{API}/{path}", headers=H, params=params, timeout=60).json()
    if body["code"] != "ok":
        raise RuntimeError(f"{body['code']}: {body['message']}")
    return body

posts, cursor = [], None
while True:
    body = get("x/users/posts/list", username="openai", **({"cursor": cursor} if cursor else {}))
    batch = body["data"]["items"]
    posts += [p for p in batch if p["published_at"] >= START]
    if not body["page"]["has_more"] or (batch and batch[-1]["published_at"] < START):
        break
    cursor = body["page"]["next_cursor"]

print(len(posts), "posts since", START)
```

For the search route, loop over months with `query=f"from:openai since:{a} until:{b}"` and `sort=latest`. Add `-filter:replies` if you only want the account's own posts and not its replies to others.

## Limits

- How deep the timeline pages go is up to X. If it stops before your start date, switch to the monthly search slices.
- Protected accounts and deleted posts cannot be collected.
- Each page is one charge, and a page that fails costs nothing.

## The official alternative

X's API returns at most the 3,200 most recent posts from a user's timeline. Its full-archive search with `from:` goes back to 2006 for pay-per-use accounts, at $0.005 per post. For one account with a few thousand posts that is a fair price, and it is the route to pick if you need X's own guarantee of completeness. For a dozen competitor accounts every week, per-page billing adds up to less. The [competitor monitoring guide](/solutions/competitor-monitoring/) shows a weekly version of this run.

## Endpoints used

- [X account posts](https://okdata.online/apis/x/users/posts/list/) `x.users.posts.list`: $0.006 per call · about 20 posts per page
- [X post search](https://okdata.online/apis/x/posts/search/) `x.posts.search`: $0.006 per call · about 20 posts per page
- [X account profile](https://okdata.online/apis/x/users/get/) `x.users.get`: $0.001 per call

Updated 2026-11-12
