---
title: "SDKs"
description: "The Python and Node clients for the Scalebrowser daemon: a typed REST client plus a direct-CDP driver, in the two languages the daemon ships clients for."
canonical: "https://scalebrowser.net/docs/sdks"
---

> ## Documentation Index
> Fetch the complete documentation index at: https://scalebrowser.net/llms.txt
> Use this file to discover all available pages before exploring further.

# SDKs

> The Python and Node clients for the Scalebrowser daemon: a typed REST client plus a direct-CDP driver, in the two languages the daemon ships clients for.

Two clients, one shape. Each is a typed wrapper around the [REST API](/docs/rest) plus a [direct-CDP](/docs/cdp) driver, so the target attach, the frame bookkeeping and the humanized input are already wired up.

They are also the only public artifact this product ships. The daemon and the engine come with your licence; the clients are MIT-licensed, because a client nobody can install is a client nobody uses.

## Install

<CodeGroup>
```bash Python
pip install scalebrowser
```

```bash Node
npm install @scalebrowser/sdk
```
</CodeGroup>

Python needs 3.10 or newer, Node 18 or newer. The Node package ships ESM and CJS side by side with type declarations.

## Connect and drive a page

Both clients take the daemon's address and your API token. `launch` does the whole dance: start the profile, open a CDP session, hand back something you can drive, and stop the profile when the block ends.

<CodeGroup>
```python Python
from scalebrowser import ScalebrowserClient, CreateProfileBody

sb = ScalebrowserClient(base_url="http://127.0.0.1:8787", token="…")

profile = sb.create_profile(CreateProfileBody(name="acct-01"))

with sb.launch(profile.id, headless=True) as page:
    page.navigate("https://example.com")
    print(page.evaluate("document.title"))
    page.humanize_click(120, 240)

sb.close()
```

```ts Node
import { ScalebrowserClient } from '@scalebrowser/sdk';

const sb = new ScalebrowserClient({
  baseUrl: 'http://127.0.0.1:8787',
  token: process.env.SCALEBROWSER_TOKEN,
});

const profile = await sb.createProfile({ name: 'acct-01' });

await using session = await sb.launch(profile.id, { headless: true });

await session.cdp.navigate('https://example.com');
const title = await session.cdp.evaluate<string>('document.title');
await session.cdp.humanizeClick(120, 220);
```
</CodeGroup>

`await using` in the Node example stops the profile and closes the CDP session when the block exits. Without it, `startProfile` returns the same `cdp_ws` endpoint the REST API returns, `connectCdp` opens the session, and you close both yourself.

Python mirrors the sync client method for method in `AsyncScalebrowserClient` for `asyncio` code.

## Every route reaches both clients

That is a rule with a test behind it rather than an intention. `sdk_coverage` compares the daemon's own route table against both clients and fails the build when a route reaches neither, which is how the gap was found in the first place: the daemon served 57 routes and the clients reached 37 and 36, missing runs, mailboxes, passkeys, interruptions, artifacts and the cookie reveal, with nothing failing anywhere.

Method names follow the route, in `snake_case` for Python and `camelCase` for Node:

| Area | What it covers |
| --- | --- |
| Profiles | `create`, `get`, `list`, `update`, `delete`, `start`, `stop` |
| Bulk | create from a preset, start, stop, delete, assign a proxy or extensions |
| Groups and presets | the full set, plus `get_persona_constraints` for the regions a preset may pin |
| Proxies | the full set, plus `check_proxy_config` to probe a configuration before saving it |
| Extensions | attach and detach per profile, and the daemon-wide library |
| Credentials and cookies | list and store; revealing a value needs the vault password |
| Sessions | export and import a profile's cookies |
| Mailboxes | where a profile's confirmation codes arrive |
| Passkeys | metadata only, because the private key has no field and no endpoint |
| Agent runs | read-only: runs, steps, screenshots, activity |
| Interruptions | who may answer when the browser asks something |
| Artifacts | hand the daemon a file, or fetch a screenshot, download or saved PDF as bytes |
| Tasks and profile memory | a profile's task list, and its `PROFILE.md` |
| Videos | recordings, renders, share links, media, voice providers, codecs |
| Secrets | the values an agent may use but not read, plus scrubbing and `run` |
| Remote access and the exit rule | read and set the two machine-local switches |
| Input, metrics, account, events | `send_input`, `get_metrics`, `get_account`, `health`, the event stream |

Four blocks are deliberately absent, each named in the coverage test with its reason. The clearest is [profile sync](/docs/sync): four of its routes carry the sync passphrase and refuse any caller that is not on loopback, so an SDK method could only ever be refused.

## The event stream

```python
async for event in sb_async.events():
    print(event.type)          # profile_started / profile_crashed / …
```

Same stream as [`/v1/events`](/docs/events), typed on the way in.

## When a call fails

Errors carry the daemon's own contract rather than a client-side interpretation: an API error has the HTTP status, the numeric code and the message. Python raises `ApiError`, `NetworkError` when the daemon is unreachable, and `CdpError` for protocol failures; Node mirrors it. The numbers are listed under [Errors](/docs/errors).

## The driver, and what it never does

The CDP session gives you `send` for any command, `navigate`, `evaluate`, event subscription, and the humanized input calls that route through the daemon.

<Warning>

**`evaluate` never calls `Runtime.enable`.** That command is a known detection signal, so the driver uses an isolated world instead. If you drop to `send` and enable it yourself, you undo that on purpose. The reasoning is on [direct CDP](/docs/cdp#why-direct-cdp-and-not-playwright).

</Warning>

## Next
- [REST API](/docs/rest): the surface both clients wrap.
- [Errors](/docs/errors) · [Events](/docs/events): the two contracts a client has to handle.
- [Direct CDP](/docs/cdp): the driver half, in more detail.
