Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@
"integrations/vercel"
]
},
{
"group": "Migrations",
"pages": [
"migrations/scrapybara"
]
},
{
"group": "Community",
"pages": [
Expand Down
172 changes: 172 additions & 0 deletions migrations/scrapybara.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
title: "Scrapybara"
---

[Scrapybara](https://scrapybara.com/) is shutting down their virtual desktop and browser service on **October 15, 2025**. If you're currently using Scrapybara for browser automation, Kernel is here to help you migrate seamlessly.

## Key Concepts

| Feature | Scrapybara | Kernel |
|---------|-----------|--------|
| **Start Browser** | `client.start_browser()` | `client.browsers.create()` |
| **Standby Mode** | `instance.pause()` / `instance.resume()` | Automatic standby mode |
| **CDP URL** | `instance.get_cdp_url().cdp_url` | Returns `cdp_ws_url` in create response |
| **Live View** | `instance.get_stream_url().stream_url` | Returns `browser_live_view_url` in create response |
| **Stealth Mode** | ❌ Not available | Create browser with `stealth: true` |
| **Replays** | ❌ Not available | `client.browsers.replays.start()` and `client.browsers.replays.stop()` |
| **Save Auth** | `instance.browser.save_auth(name="default")` | Create [Profile](/browsers/profiles). Then create browser with `kernel.browsers.create(profile={"name": "profile1", "save_changes": True})` |

## How to migrate

### Basic Browser Creation

**Scrapybara**
```python
from scrapybara import Scrapybara
from playwright.async_api import async_playwright

client = Scrapybara(api_key="your_api_key")
instance = client.start_browser(timeout_hours=1)
cdp_url = instance.get_cdp_url().cdp_url

async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(cdp_url)
page = browser.contexts[0].pages[0]
await page.goto("https://example.com")
await browser.close()

instance.stop()
```

**Kernel**
```python
from kernel import Kernel
from playwright.async_api import async_playwright

client = Kernel(api_key="your_api_key")
kernel_browser = client.browsers.create(timeout_seconds=3600)
cdp_url = kernel_browser.cdp_ws_url

async with async_playwright() as p:
browser = await p.chromium.connect_over_cdp(cdp_url)
page = browser.contexts[0].pages[0]
await page.goto("https://example.com")
await browser.close()

await client.browsers.delete_by_id(kernel_browser.session_id)
```

### Save & Reuse Authentication

**Scrapybara**
```python
# First session - save auth
instance = client.start_browser()
# ... login to website via Playwright ...
auth_state = instance.browser.save_auth(name="my-login")
instance.stop()

# Second session - load auth
instance2 = client.start_browser()
instance2.browser.authenticate(auth_state_id=auth_state.auth_state_id)
# ... browser now has saved cookies ...
```

**Kernel**
```python
# First session - save auth
profile = await client.profiles.create(name="my-login")
browser1 = await client.browsers.create(
profile={"name": "my-login", "save_changes": True}
)
# ... login to website via Playwright ...
await client.browsers.delete_by_id(browser1.session_id)

# Second session - load auth
browser2 = await client.browsers.create(
profile={"name": "my-login"}
)
# ... browser now has saved cookies ...
```

### File Download

**Scrapybara**
```python
instance = client.start_browser()
# ... trigger download in browser ...
# Then use file operations
downloaded_file = instance.file(command="read", path="/download/path")
```

**Kernel**
```python
browser = await client.browsers.create()
# ... trigger download in browser via Playwright ...
# Then read from filesystem
file_response = await client.browsers.fs.read_file(
browser.session_id,
path="/tmp/downloads/file.pdf"
)
await file_response.write_to_file("local-file.pdf")
```

### Long-Running Sessions

**Scrapybara**
```python
# Pause/resume for long-running sessions
instance = client.start_browser(timeout_hours=24)
# ... do some work ...
instance.pause() # Pause to save costs
# ... later ...
instance.resume() # Resume work
```

**Kernel**
```python
# Automatic standby mode + persistence
browser = await client.browsers.create(
persistence={"id": "my-long-session"}
)
# ... do some work ...
# Browser enters standby mode between connections

# Later - reuse the exact browser instance with full state
browser2 = await client.browsers.create(
persistence={"id": "my-long-session"}
)
```


## Full API Comparison

| Feature | Scrapybara | Kernel |
|---------|-----------|--------|
| **Create Browser** | `client.start_browser()` | `client.browsers.create()` |
| **Get CDP URL** | `instance.get_cdp_url().cdp_url` | Returns `cdp_ws_url` in create response |
| **Get Live View** | `instance.get_stream_url().stream_url` | Returns `browser_live_view_url` in create response |
| **Delete Browser** | `instance.stop()` | `client.browsers.delete_by_id(session_id)` |
| **List Browsers** | `client.get_instances()` | `client.browsers.list()` |
| **Save Auth State** | `instance.browser.save_auth(name="default")` | Create [Profile](/browsers/profiles). Then create browser with `kernel.browsers.create(profile={"name": "profile1", "save_changes": True})` |
| **Load Auth State** | `instance.browser.authenticate(auth_state_id="xyz")` | `kernel.browsers.create(profile={"name": "profile1"})` |
| **Pause/Resume** | `instance.pause()` / `instance.resume()` | Automatic standby mode |
| **Screenshot** | `instance.screenshot()` | Use Playwright or Puppeteer |
| **Timeout Config** | `timeout_hours` parameter | `timeout_seconds` parameter |
| **Stealth Mode** | ❌ Not available | Create browser with `stealth: true` |
| **Headless Mode** | ❌ Not available | Create browser with `headless: true` |
| **Session Persistence** | Auth state only | Full browser state via creating browser with `persistence={"id": "persist-id"}` |
| **Video Replays** | ❌ Not available | `client.browsers.replays.start()` and `client.browsers.replays.stop()` |
| **File Upload** | `instance.upload()` | `client.browsers.fs.upload()` or Playwright |
| **File Download** | Via browser, then `instance.file()` | `client.browsers.fs.read_file()` |
| **Process Control** | `instance.bash()` | `client.browsers.process.*` |
| **Proxy Support** | ❌ Not available | Create [Proxy](/proxies/overview#1-create-a-proxy). Then create browser with `client.browsers.create(proxy_id=proxy.id)` |

---

## Need Help?

* **Contact Us** on [Discord](https://discord.gg/FBrveQRcud)
* **Sign-Up** [here](https://dashboard.onkernel.com/sign-up)
* **Check out** our open source repos [here](https://github.com/onkernel/kernel-images)