okdata for Python
Social data for AI agents, paid per call: Douyin, Xiaohongshu, WeChat, Bilibili, Weibo, Kuaishou, Zhihu, TikTok, X, YouTube, Instagram, Reddit and more, as one API with one envelope and one error format. Every endpoint is a typed method generated from the okdata catalog, with its price in its docstring.
pip install okdata # Python 3.9+, one dependency (httpx)
export OKDATA_API_KEY=okd_...
No key yet? Sign up at okdata.online (中文:注册).
First call
The Playground's Python tab shows the raw HTTP request; with the SDK the same call is:
from okdata import OkData
ok = OkData() # reads OKDATA_API_KEY; OkData("okd_...") works too
page = ok.douyin.videos.search(query="露营装备", sort="latest", max_price="0.05")
for row in page.items:
print(row["id"], row["metrics"]["likes"], row["text"][:60])
print("cost: $" + page.cost)
Parameters are flat and named as in the API (query, id, url, cursor, ...). Every method also
takes view (compact | standard | full, same price), fields (["id", "text"] or "id,text"),
max_price (sent as X-Max-Price: a call that could cost more is refused before it runs, never
charged), idempotency_key and timeout. Any endpoint also works by id:
ok.call("weibo.trends.list"), including ids newer than your SDK version.
What comes back: Page (list endpoints: items, next_cursor, has_more), Item (one object:
item) or Batch (ids=[...] on endpoints that take a list: items, missing). Each has cost,
balance_after, request_id, result_status, replayed, warnings, meta and the raw envelope.
Items are plain dicts, typed as TypedDicts (Post, Account, Comment, ...).
Paging within a budget
for page in ok.pages("douyin.videos.comments.list", id="7301234567890123456", max_pages=5, max_spend="0.01"):
...
items = ok.items("x.posts.search", query="claude code", max_items=200, max_spend="0.05")
rows = list(items)
print(items.spent, items.stop_reason) # "0.03", "max_items" | "max_spend" | "end" | "balance" | "max_pages"
Each page is a separate, separately charged call. Before each page the pager adds what that page could
cost at most (the endpoint's max_charge) and stops if the total would pass max_spend; each call also
carries X-Max-Price set to what is left, so the server refuses (free) anything dearer.
Retries and idempotency
Every paid call gets an Idempotency-Key, reused by its retries, so a retry is never charged twice.
Retries follow the error body: retry yes / same_key are retried (after retry_after_seconds when
given; a wait longer than max_retry_delay raises instead), once gets one more try, no and
after_fix are never retried. Defaults: max_retries=2, timeout=65 seconds per attempt.
Errors
from okdata import OkDataError
try:
ok.x.posts.get(id="1850000000000000000")
except OkDataError as err:
err.code, err.charged, err.retry, err.request_id # branch on code, never on message
err.message, err.message_zh, err.problems, err.param, err.reason, err.retry_after_seconds
charged is False for almost every error, True for a not_found the endpoint charges (amount
says how much) and None when it is not known yet (a lost answer, settlement_unknown): look it up
with ok.calls.get(err.request_id) or ok.calls.by_key(err.idempotency_key). A lost connection raises
OkDataConnectionError (connection_error or client_timeout, charged=None). The codes are in
okdata.ERROR_CODES and at https://okdata.online/docs/errors/.
Async
import asyncio
from okdata import AsyncOkData
async def main():
async with AsyncOkData() as ok:
page = await ok.weibo.trends.list()
async for row in ok.items("douyin.videos.search", query="露营装备", max_spend="0.1"):
print(row["id"])
asyncio.run(main())
Free routes
ok.catalog(), ok.status() (no key needed), ok.account() (balance, key limits, rate tier),
ok.usage(group_by=["day", "capability"]), ok.calls.get(request_id), ok.calls.result(request_id, view="full") (a result kept 24 h, read again for free) and ok.calls.by_key(idempotency_key).
Options
OkData(api_key=None, *, base_url=None, timeout=65.0, max_retries=2, retry_base_delay=0.5, max_retry_delay=20.0, source=None, end_user=None, user_agent=None, http_client=None). base_url
defaults to OKDATA_BASE_URL, then https://api.okdata.online. source and end_user are sent as
X-Source and X-End-User for your usage figures; every call carries X-Entry: sdk.
MIT licensed.
Metadata
Release files for okdata 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| okdata-0.1.0.tar.gz | 108.6 kB | Without provenance | Details for okdata-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| okdata-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for okdata-0.1.0-py3-none-any.whl |
Total release size: 217.7 kB
Release files / okdata-0.1.0.tar.gz
| Download URL | okdata-0.1.0.tar.gz |
|---|---|
| Size | 108.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fc898a3c2cc3a676adc68487d562549767c50a12672675350aed48db986cfaed
|
|
BLAKE2b-256 checksum How to use checksums |
5aa2bb48cf813f3d8439c60a689aafb97d3b47a440376d9424206af792e2a15d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / okdata-0.1.0-py3-none-any.whl
| Download URL | okdata-0.1.0-py3-none-any.whl |
|---|---|
| Size | 109.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
99fc99c817d813f7d91f755ba4b7025d5b6e4d435d769a889ce49b53751c8436
|
|
BLAKE2b-256 checksum How to use checksums |
2832673af14222a73234f8fda4d298d2260de63d8f3239be2164c39cab46126e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.20 {"installer":{"name":"uv","version":"0.9.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for okdata 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.