Skip to main content
The official Python client. Pure Python: one py3-none-any wheel for every operating system, no compiler required on any of them, one runtime dependency (httpx, itself pure Python).

Installation

Requires Python 3.10 or newer.

Quick start

Async and context managed throughout, a genuinely different shape from the TypeScript client. await and async for on the same job object are two separate requests against one durable row, watching a run and having its answer is not a choice between them.

Configuration

The same two names the TypeScript SDK and the CLI read. Neither SDK uses the CLI’s stored outcrawl login session: a script needs OUTCRAWL_API_KEY or a key passed in. Pass Outcrawl(api_key=..., base_url=...) to override per client.

Surface

Every one of the 46 capabilities is reachable except live browser control.
  • oc.scrape(url, **options) / oc.crawl(url, **options) / oc.search(query, **options). await oc.crawl(url) gives you a crawl you read with async for, one page at a time as each is fetched.
  • oc.crawl.job(id) reaches a crawl already in progress: status(), results(), cancel(). Useful when a connection drops, hanging up on a streaming crawl cancels it, but the pages already delivered stay yours; these routes are how you read what was already paid for.
  • oc.agent(task=..., caps=...). caps is required at runtime and caps.budget inside it; caps.steps and caps.duration are optional. The job is awaitable, async-iterable, and carries status(), results(), events(), cancel(), control(), answer(), add_file(). schema accepts a JSON Schema object and constrains run["data"] to it, the same typed submit the TypeScript SDK documents.
  • oc.profiles, oc.secrets, oc.rules, oc.integrations, oc.sessions, oc.monitors.
  • oc.usage(**query) and oc.credits(). Every credit figure is a decimal string, use decimal.Decimal, never float().

What is not here

oc.browser(). Live browser control needs a CDP connection held open in the caller’s own process, which is why it exists only in the TypeScript SDK. The same underlying page capability is reachable through agent and scrape, which run the loop on the platform’s own side, a difference in kind rather than an omission. Session.take_control() is absent for the identical reason, it opens a CDP connection to a running session’s own page so a person can drive it directly.

Errors

The same classes, same fields, same messages as the TypeScript SDK, kept in parity by a shared test fixture so neither client can drift from the other silently.
Branch on error.code, never on str(error). See errors for the full table.