Skip to content

Commit 607a27f

Browse files
authored
Merge branch 'main' into mason/add-copy-page-to-context-menu
2 parents b780c97 + 4094f38 commit 607a27f

File tree

8 files changed

+191
-13
lines changed

8 files changed

+191
-13
lines changed

docs.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@
112112
"integrations/vercel"
113113
]
114114
},
115+
{
116+
"group": "Migrations",
117+
"pages": [
118+
"migrations/scrapybara"
119+
]
120+
},
115121
{
116122
"group": "Community",
117123
"pages": [

migrations/scrapybara.mdx

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
---
2+
title: "Scrapybara"
3+
---
4+
5+
[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.
6+
7+
## Key Concepts
8+
9+
| Feature | Scrapybara | Kernel |
10+
|---------|-----------|--------|
11+
| **Start Browser** | `client.start_browser()` | `client.browsers.create()` |
12+
| **Standby Mode** | `instance.pause()` / `instance.resume()` | Automatic standby mode |
13+
| **CDP URL** | `instance.get_cdp_url().cdp_url` | Returns `cdp_ws_url` in create response |
14+
| **Live View** | `instance.get_stream_url().stream_url` | Returns `browser_live_view_url` in create response |
15+
| **Stealth Mode** | ❌ Not available | Create browser with `stealth: true` |
16+
| **Replays** | ❌ Not available | `client.browsers.replays.start()` and `client.browsers.replays.stop()` |
17+
| **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})` |
18+
19+
## How to migrate
20+
21+
### Basic Browser Creation
22+
23+
**Scrapybara**
24+
```python
25+
from scrapybara import Scrapybara
26+
from playwright.async_api import async_playwright
27+
28+
client = Scrapybara(api_key="your_api_key")
29+
instance = client.start_browser(timeout_hours=1)
30+
cdp_url = instance.get_cdp_url().cdp_url
31+
32+
async with async_playwright() as p:
33+
browser = await p.chromium.connect_over_cdp(cdp_url)
34+
page = browser.contexts[0].pages[0]
35+
await page.goto("https://example.com")
36+
await browser.close()
37+
38+
instance.stop()
39+
```
40+
41+
**Kernel**
42+
```python
43+
from kernel import Kernel
44+
from playwright.async_api import async_playwright
45+
46+
client = Kernel(api_key="your_api_key")
47+
kernel_browser = client.browsers.create(timeout_seconds=3600)
48+
cdp_url = kernel_browser.cdp_ws_url
49+
50+
async with async_playwright() as p:
51+
browser = await p.chromium.connect_over_cdp(cdp_url)
52+
page = browser.contexts[0].pages[0]
53+
await page.goto("https://example.com")
54+
await browser.close()
55+
56+
await client.browsers.delete_by_id(kernel_browser.session_id)
57+
```
58+
59+
### Save & Reuse Authentication
60+
61+
**Scrapybara**
62+
```python
63+
# First session - save auth
64+
instance = client.start_browser()
65+
# ... login to website via Playwright ...
66+
auth_state = instance.browser.save_auth(name="my-login")
67+
instance.stop()
68+
69+
# Second session - load auth
70+
instance2 = client.start_browser()
71+
instance2.browser.authenticate(auth_state_id=auth_state.auth_state_id)
72+
# ... browser now has saved cookies ...
73+
```
74+
75+
**Kernel**
76+
```python
77+
# First session - save auth
78+
profile = await client.profiles.create(name="my-login")
79+
browser1 = await client.browsers.create(
80+
profile={"name": "my-login", "save_changes": True}
81+
)
82+
# ... login to website via Playwright ...
83+
await client.browsers.delete_by_id(browser1.session_id)
84+
85+
# Second session - load auth
86+
browser2 = await client.browsers.create(
87+
profile={"name": "my-login"}
88+
)
89+
# ... browser now has saved cookies ...
90+
```
91+
92+
### File Download
93+
94+
**Scrapybara**
95+
```python
96+
instance = client.start_browser()
97+
# ... trigger download in browser ...
98+
# Then use file operations
99+
downloaded_file = instance.file(command="read", path="/download/path")
100+
```
101+
102+
**Kernel**
103+
```python
104+
browser = await client.browsers.create()
105+
# ... trigger download in browser via Playwright ...
106+
# Then read from filesystem
107+
file_response = await client.browsers.fs.read_file(
108+
browser.session_id,
109+
path="/tmp/downloads/file.pdf"
110+
)
111+
await file_response.write_to_file("local-file.pdf")
112+
```
113+
114+
### Long-Running Sessions
115+
116+
**Scrapybara**
117+
```python
118+
# Pause/resume for long-running sessions
119+
instance = client.start_browser(timeout_hours=24)
120+
# ... do some work ...
121+
instance.pause() # Pause to save costs
122+
# ... later ...
123+
instance.resume() # Resume work
124+
```
125+
126+
**Kernel**
127+
```python
128+
# Automatic standby mode + persistence
129+
browser = await client.browsers.create(
130+
persistence={"id": "my-long-session"}
131+
)
132+
# ... do some work ...
133+
# Browser enters standby mode between connections
134+
135+
# Later - reuse the exact browser instance with full state
136+
browser2 = await client.browsers.create(
137+
persistence={"id": "my-long-session"}
138+
)
139+
```
140+
141+
142+
## Full API Comparison
143+
144+
| Feature | Scrapybara | Kernel |
145+
|---------|-----------|--------|
146+
| **Create Browser** | `client.start_browser()` | `client.browsers.create()` |
147+
| **Get CDP URL** | `instance.get_cdp_url().cdp_url` | Returns `cdp_ws_url` in create response |
148+
| **Get Live View** | `instance.get_stream_url().stream_url` | Returns `browser_live_view_url` in create response |
149+
| **Delete Browser** | `instance.stop()` | `client.browsers.delete_by_id(session_id)` |
150+
| **List Browsers** | `client.get_instances()` | `client.browsers.list()` |
151+
| **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})` |
152+
| **Load Auth State** | `instance.browser.authenticate(auth_state_id="xyz")` | `kernel.browsers.create(profile={"name": "profile1"})` |
153+
| **Pause/Resume** | `instance.pause()` / `instance.resume()` | Automatic standby mode |
154+
| **Screenshot** | `instance.screenshot()` | Use Playwright or Puppeteer |
155+
| **Timeout Config** | `timeout_hours` parameter | `timeout_seconds` parameter |
156+
| **Stealth Mode** | ❌ Not available | Create browser with `stealth: true` |
157+
| **Headless Mode** | ❌ Not available | Create browser with `headless: true` |
158+
| **Session Persistence** | Auth state only | Full browser state via creating browser with `persistence={"id": "persist-id"}` |
159+
| **Video Replays** | ❌ Not available | `client.browsers.replays.start()` and `client.browsers.replays.stop()` |
160+
| **File Upload** | `instance.upload()` | `client.browsers.fs.upload()` or Playwright |
161+
| **File Download** | Via browser, then `instance.file()` | `client.browsers.fs.read_file()` |
162+
| **Process Control** | `instance.bash()` | `client.browsers.process.*` |
163+
| **Proxy Support** | ❌ Not available | Create [Proxy](/proxies/overview#1-create-a-proxy). Then create browser with `client.browsers.create(proxy_id=proxy.id)` |
164+
165+
---
166+
167+
## Need Help?
168+
169+
* **Contact Us** on [Discord](https://discord.gg/FBrveQRcud)
170+
* **Sign-Up** [here](https://dashboard.onkernel.com/sign-up)
171+
* **Check out** our open source repos [here](https://github.com/onkernel/kernel-images)
172+

proxies/custom.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Custom proxies allow you to use your own proxy servers with Kernel browsers. Thi
77
## Configuration
88

99
<Tip>
10-
Currently, only HTTPS proxies are supported for custom proxy configurations.
10+
HTTP and HTTPS proxies are supported for custom proxy configurations. If no protocol is specified, HTTPS is used by default.
1111
</Tip>
1212

1313
Specify the host, port, and optional authentication credentials for your proxy server:
@@ -20,7 +20,7 @@ const kernel = new Kernel();
2020

2121
const proxy = await kernel.proxies.create({
2222
type: 'custom',
23-
name: 'My Private Proxy',
23+
name: 'my-private-proxy',
2424
config: {
2525
host: 'proxy.example.com',
2626
port: 443,
@@ -40,7 +40,7 @@ client = kernel.Kernel()
4040

4141
proxy = client.proxies.create(
4242
type='custom',
43-
name='My Private Proxy',
43+
name='my-private-proxy',
4444
config={
4545
'host': 'proxy.example.com',
4646
'port': 443,

proxies/datacenter.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const kernel = new Kernel();
1616

1717
const proxy = await kernel.proxies.create({
1818
type: 'datacenter',
19-
name: 'US Datacenter',
19+
name: 'my-us-datacenter',
2020
config: {
2121
country: 'US'
2222
}
@@ -33,7 +33,7 @@ client = kernel.Kernel()
3333

3434
proxy = client.proxies.create(
3535
type='datacenter',
36-
name='US Datacenter',
36+
name='my-us-datacenter',
3737
config={
3838
'country': 'US'
3939
}

proxies/isp.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const kernel = new Kernel();
1616

1717
const proxy = await kernel.proxies.create({
1818
type: 'isp',
19-
name: 'My ISP Proxy'
19+
name: 'my-isp-proxy'
2020
});
2121

2222
const browser = await kernel.browsers.create({
@@ -30,7 +30,7 @@ client = kernel.Kernel()
3030

3131
proxy = client.proxies.create(
3232
type='isp',
33-
name='My ISP Proxy'
33+
name='my-isp-proxy'
3434
)
3535

3636
browser = client.browsers.create(

proxies/mobile.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const kernel = new Kernel();
1616

1717
const proxy = await kernel.proxies.create({
1818
type: 'mobile',
19-
name: 'T-Mobile Proxy',
19+
name: 'my-tmobile-proxy',
2020
config: {
2121
carrier: 'tmobile'
2222
}
@@ -33,7 +33,7 @@ client = kernel.Kernel()
3333

3434
proxy = client.proxies.create(
3535
type='mobile',
36-
name='T-Mobile Proxy',
36+
name='my-tmobile-proxy',
3737
config={
3838
'carrier': 'tmobile'
3939
}

proxies/overview.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const kernel = new Kernel();
4343
// Create or use existing proxy
4444
const proxy = await kernel.proxies.create({
4545
type: 'residential',
46-
name: 'US Residential',
46+
name: 'my-us-residential',
4747
config: {
4848
country: 'US'
4949
}
@@ -62,7 +62,7 @@ client = kernel.Kernel()
6262
# Create or use existing proxy
6363
proxy = client.proxies.create(
6464
type='residential',
65-
name='US Residential',
65+
name='my-us-residential',
6666
config={
6767
'country': 'US'
6868
}

proxies/residential.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const kernel = new Kernel();
1616

1717
const proxy = await kernel.proxies.create({
1818
type: 'residential',
19-
name: 'California Residential',
19+
name: 'my-california-residential',
2020
config: {
2121
country: 'US',
2222
city: 'sanfrancisco',
@@ -36,7 +36,7 @@ client = kernel.Kernel()
3636

3737
proxy = client.proxies.create(
3838
type='residential',
39-
name='California Residential',
39+
name='my-california-residential',
4040
config={
4141
'country': 'US',
4242
'city': 'sanfrancisco',

0 commit comments

Comments
 (0)