Skip to main content

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)

Source distribution for okdata 0.1.0
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)

Table of built distributions (wheels) for okdata 0.1.0
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page