# What rate limits does a social data API have, and how should I handle 429 errors?

> How rate limits work on a social data API for Bilibili or Weibo jobs: burst and refill per key, the headers that show where you stand, and a pacer that avoids 429s.

Canonical page: https://okdata.online/answers/social-data-api-rate-limits-429/

**Short answer: **On okdata each key can send a short burst of calls and then a steady number per second; your account details and the headers on every response show where you stand. Going over returns a 429 that is never charged and says how long to wait, so the fix is to wait and resend. Pace large jobs to the steady rate: 10,000 Bilibili comment pages cost $20.00 whether they run in an hour or a day.

When you scrape a platform yourself, a 429 is a warning about your account: twscrape users know the message [Ban detected: 429, (88) Rate limit exceeded](https://github.com/vladkens/twscrape/issues/274). From a data API, a 429 only means you are sending faster than your key allows. Nothing gets banned, nothing is charged, and the response tells you when to try again.

## How the limit works

Each key has a token bucket: a burst of calls you can make at once, refilled at a steady rate per second.

```bash
curl -s "https://api.okdata.online/v1/account" -H "Authorization: Bearer $OKDATA_API_KEY" | jq '.data.rate_limit'
# {"tier": "...", "burst": ..., "per_second": ...}
```

Every keyed response also carries:

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` | burst size |
| `X-RateLimit-Remaining` | calls left in the bucket right now |
| `X-RateLimit-Reset` | seconds until the bucket is full again |
| `Retry-After` | on a 429 only: seconds to wait |

The 429 body is the standard error: `code: "rate_limited"`, `charged: false`, `retry: "yes"` and `retry_after_seconds`.

## Pace the job instead of fighting 429s

```python
import os, time, requests

H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
limit = requests.get("https://api.okdata.online/v1/account", headers=H, timeout=30).json()["data"]["rate_limit"]
gap = 1 / limit["per_second"]                     # steady pace the bucket can sustain

def get(path, **params):
    while True:
        r = requests.get(f"https://api.okdata.online{path}", headers=H, params=params, timeout=60)
        body = r.json()
        if body["code"] != "rate_limited":
            time.sleep(gap)
            return body
        time.sleep(body["retry_after_seconds"])     # free; just wait and resend

for bv in ["BV1xx411c7mD"]:
    page = get("/v1/bilibili/videos/comments/list", id=bv, sort="hot")
```

Run several workers only up to the burst size, and lower the pace if `X-RateLimit-Remaining` keeps hitting zero.

## Plan big jobs by time, not just money

At a refill rate of r calls a second, N calls take about N ÷ r seconds. The cost does not change with speed: [Bilibili video comments](/apis/bilibili/videos/comments/list/) is $0.002 a page, [Bilibili video search](/apis/bilibili/videos/search/) $0.002, and [Weibo post search](/apis/weibo/posts/search/) $0.002, whether you send them in a burst or spread over a night. If a deadline needs more throughput than your key allows, ask hello@okdata.online about a higher tier.

## Gotchas

- Limits are per key. Two scripts sharing one key share one bucket.
- A retry with the same `Idempotency-Key` while the first attempt is still running also returns `rate_limited`, with a one-second wait.
- Platform-side limits still exist upstream. When a source is saturated you get `upstream_busy`, also free; back off longer.

The [errors page](/docs/errors/) lists every code with its retry advice.

## Endpoints used

- [Bilibili video search](https://okdata.online/apis/bilibili/videos/search/) `bilibili.videos.search`: $0.002 per call · about 20 videos per page
- [Bilibili video comments](https://okdata.online/apis/bilibili/videos/comments/list/) `bilibili.videos.comments.list`: $0.002 per call · about 20 comments per page
- [Weibo post search](https://okdata.online/apis/weibo/posts/search/) `weibo.posts.search`: $0.002 per call · about 10 posts per page

Updated 2026-11-12
