---
title: "Migrate from Browserbase to a local browser"
description: "Move Browserbase code to a Scalebrowser profile on your own machine: swap the session's connect URL for cdp_ws, a context for the profile, and its proxies for the profile's."
canonical: "https://scalebrowser.net/docs/migrate/browserbase"
---

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

# Migrate from Browserbase to a local browser

> Move Browserbase code to a Scalebrowser profile on your own machine: swap the session's connect URL for cdp_ws, a context for the profile, and its proxies for the profile's.

Browserbase code already talks to a remote Chromium over CDP, usually through Playwright's `connect_over_cdp`. A Scalebrowser profile hands out the same kind of address, so the code that drives the page stays as it is. What moves is where the browser runs: on your own machine, with its own hardware and its own exit, instead of on the vendor's.

## Swap the session for a profile

<CodeGroup>
```python Before: Browserbase
bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
session = bb.sessions.create()
browser = playwright.chromium.connect_over_cdp(session.connect_url)
page = browser.contexts[0].pages[0]
```

```python After: Scalebrowser
sb = ScalebrowserClient(base_url="http://127.0.0.1:8787", token=os.environ["SCALEBROWSER_TOKEN"])
started = sb.start_profile(PROFILE_ID)
browser = playwright.chromium.connect_over_cdp(started.cdp_ws, no_defaults=True)
context = browser.contexts[0]
page = context.pages[0] if context.pages else context.new_page()
# … your code, unchanged …
browser.close()
sb.stop_profile(PROFILE_ID)
```

```ts After: Scalebrowser (Node)
const sb = new ScalebrowserClient({
  baseUrl: 'http://127.0.0.1:8787',
  token: process.env.SCALEBROWSER_TOKEN,
});
const started = await sb.startProfile(profileId);
const browser = await chromium.connectOverCDP(started.cdp_ws, { noDefaults: true });
const context = browser.contexts()[0];
const page = context.pages()[0] ?? (await context.newPage());
// … your code, unchanged …
await browser.close();
await sb.stopProfile(profileId);
```
</CodeGroup>

The rule Browserbase gives, use the default context and its page, holds here too and for a stronger reason: `contexts[0]` is the profile, and a context you create yourself is a throwaway one outside it. The [Playwright guide](/docs/migrate/playwright) covers the other differences of an attached browser.

## What maps to what

| Browserbase | Scalebrowser |
| --- | --- |
| A session, created per run | A profile, created once and started per run. It runs until you stop it; there is no session timeout and no five-minute window to connect |
| A context with `persist: true` | The profile itself. Cookies, storage and logins persist between starts, with nothing to wait for after a close |
| `proxies`, built-in or external | A proxy stored once and assigned to the profile: HTTP, SOCKS5 or a provider's gateway. See [Proxies & exits](/docs/proxies) |
| `region` | The proxy's exit decides where the profile appears to be, and its timezone and locale follow the exit |
| Fingerprint and stealth settings | Nothing to set. The profile's identity is drawn from its seed, and its GPU and display are the machine's own |
| Billing per browser minute | A plan counts browsers running at the same time and machines, not minutes. Profiles are unlimited. See [Plans & limits](/docs/account/plans) |
| The session live view | The [management app](/docs/ui) on your machine, and a visible window when you start with `headless: false` |

## What you take on

A cloud browser needs nothing from you but an API key. A profile needs a machine to run on, and that is the point and the cost at once:

- **A Windows machine with a real GPU.** A software renderer is visible from the page, so a launch on one is refused. See [Coherence & proxies](/docs/coherence).
- **Your own proxy for real work.** Without one, a profile leaves from your own address. A residential or mobile exit is what strict sites expect.
- **Capacity is your hardware.** A running browser takes 250 to 400 MB; how many run at once is decided by your plan and your machine together.

In return the browser and its profile data run on hardware you control, and the page talks to a browser whose hardware answers the same questions a real one would. [Profile sync](/docs/sync) moves a profile between your own machines encrypted, with a key the control plane never holds.

## Beyond `connect_over_cdp`

Once the code runs against a profile, the next step is the same as for any Playwright script: for sites that grade input, drive the page with the [SDKs](/docs/sdks), whose clicks and keystrokes go through the [human input layer](/docs/behaviour). If an AI agent does the driving, the [MCP server](/docs/agents/mcp-server) is shorter still.

## Next

- [Quickstart](/docs/quickstart): a running daemon and a first profile in five steps.
- [Proxies & exits](/docs/proxies): one gateway, many profiles, one address each.
- [Migrate overview](/docs/migrate): the two steps, and what maps to what.
