# twscrape says No active accounts and my X accounts keep getting locked. What now?

> Replace a twscrape account pool with an API key: which X endpoints match search, user_tweets and user_by_login, what a page costs, and what twscrape still does better.

Canonical page: https://okdata.online/answers/twscrape-no-active-accounts/

**Short answer: **Swap the account pool for an API key. X post search ($0.006 per page of about 20 posts) replaces twscrape's search, and X account posts ($0.006 per page) replaces user_tweets, with no X login, cookies or proxies. 1,000 posts from search cost $0.30.

The usual story: a nightly job pulls posts for 40 keywords through twscrape, X locks two accounts, the rest hit their limits, and the log ends with No active accounts. Buying more accounts and proxies buys a few weeks. If the job only reads public posts and profiles, you can drop the pool and call an API with a key instead. Nothing logs in to X on your side, so there is nothing to lock.

## What maps to what

| twscrape | okdata endpoint | Price |
|---|---|---|
| `api.search(query)` | [X post search](/apis/x/posts/search/) | $0.006 per page |
| `api.user_tweets(uid)` | [X account posts](/apis/x/users/posts/list/) | $0.006 per page |
| `api.user_by_login(login)` | [X account profile](/apis/x/users/get/) | $0.001 |
| `api.tweet_details(id)` | [X post detail](/apis/x/posts/get/) | $0.001 |

Search takes the same query you would type into X, operators included, and `sort` is `latest` or `top`. Account calls take the handle, not the numeric user ID.

## The search loop, rewritten

```python
import os, requests

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

def search(query, pages=5):
    cursor, posts = None, []
    for _ in range(pages):
        params = {"query": query, "sort": "latest"}
        if cursor:
            params["cursor"] = cursor
        body = requests.get(f"{API}/x/posts/search", headers=H, params=params, timeout=60).json()
        if body["code"] != "ok":
            raise RuntimeError(f"{body['code']}: {body['message']}")
        posts += body["data"]["items"]
        if not body["page"]["has_more"]:
            break
        cursor = body["page"]["next_cursor"]
    return posts

for p in search('"vector database" -filter:replies lang:en'):
    print(p["published_at"], p["author"]["username"], p["metrics"]["likes"], p["text"][:80])
```

Each post has `text`, `published_at`, `url`, `lang`, the author with follower count, and `metrics` with views, likes, replies (`comments`), reposts and bookmarks (`favorites`).

## What a nightly job costs

40 keywords at 3 pages each is 120 calls a night: $0.72, or about $21.60 for a 30-day month. Each page is a separate charge, failed calls are free, and a `rate_limited` reply tells you how many seconds to wait. The retry rules are on the [errors page](/docs/errors/).

## What you give up

- Follower and following lists, likers, retweeters and list timelines are not in the catalog. twscrape gets those, if you keep accounts alive.
- There is no reply-thread endpoint. Replies to an account can be found with a `to:handle` search, one page at a time.
- You see what X search shows to the public: no protected accounts, nothing deleted.

If you need the graph data or a very large daily volume, a carefully paced twscrape pool or X's own API is still the better fit. For a keyword or account feed, a key is less to babysit. The [word-of-mouth guide](/solutions/word-of-mouth/) shows a full monitoring run.

## Endpoints used

- [X post search](https://okdata.online/apis/x/posts/search/) `x.posts.search`: $0.006 per call · about 20 posts per page
- [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 account profile](https://okdata.online/apis/x/users/get/) `x.users.get`: $0.001 per call
- [X post detail](https://okdata.online/apis/x/posts/get/) `x.posts.get`: $0.001 per call

Updated 2026-11-12
