Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
44e3773
docs: Add app preview example section
beran-t Mar 17, 2026
0e007e9
fix: Use e2b base SDK instead of e2b-code-interpreter
beran-t Mar 17, 2026
fcb34ce
docs: Wrap full example in accordion component
beran-t Mar 17, 2026
f8e8401
docs: Use expandable code block instead of accordion for full example
beran-t Mar 17, 2026
4fab1f9
docs: Move app preview to use-cases/browser-use
beran-t Mar 17, 2026
13e418a
Merge branch 'main' into add-app-preview-example
beran-t Mar 17, 2026
0bf9040
docs: Use globe icon for browser use page
beran-t Mar 17, 2026
47c28f8
docs: Add agent browser use case and reorganize browser use section
beran-t Mar 17, 2026
61451bc
docs: Merge browser pages into single Kernel integration page
beran-t Mar 24, 2026
6d2af4f
docs: Move Kernel page to use-cases/remote-browser
beran-t Mar 24, 2026
b3fd603
docs: Improve remote browser page flow and structure
beran-t Mar 24, 2026
aca66d3
docs: Remove cost framing from remote browser benefits
beran-t Mar 24, 2026
6b8fd28
docs: Improve remote browser page flow and structure
beran-t Mar 24, 2026
e23e7d1
docs: Fix template names, split mixed-context code, link MCP docs
beran-t Mar 24, 2026
5e36134
docs: Rework remote browser page with three focused examples
beran-t Mar 25, 2026
c3c2002
docs: Address PR review comments on remote browser page
beran-t Mar 26, 2026
d103b58
docs: Add full expandable examples and define FASTAPI_APP
beran-t Mar 26, 2026
07aeaef
docs: Rename to cloud browser, update Kernel links and descriptions
beran-t Apr 8, 2026
a8de928
docs: Update Kernel API key link to dashboard URL
beran-t Apr 9, 2026
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
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
"pages": [
"docs/use-cases/coding-agents",
"docs/use-cases/computer-use",
"docs/use-cases/ci-cd"
"docs/use-cases/ci-cd",
"docs/use-cases/remote-browser"
]
},
{
Expand Down
383 changes: 383 additions & 0 deletions docs/use-cases/remote-browser.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,383 @@
---
title: "Remote browser"
description: "Use Kernel cloud browsers with E2B sandboxes for web scraping, screenshots, and autonomous browsing agents."
icon: "globe"
---

<Note>
This guide covers **remote browsers** powered by [Kernel](https://www.kernel.computer/) — cloud Chromium instances your code controls via [CDP](https://chromedevtools.github.io/devtools-protocol/) or the [Kernel SDK](https://www.kernel.sh/docs/sdk/overview). For **local browser automation** using a virtual desktop, see [Computer use](/docs/use-cases/computer-use).
</Note>

Remote browsers run on Kernel's infrastructure, not inside your sandbox. Your agent connects to them over the network via Playwright or Puppeteer. This keeps sandboxes lightweight and lets you spin up many browsers in parallel.

Kernel handles stealth mode, CAPTCHA solving, residential proxies, and persistent browser profiles out of the box.

## Prerequisites

- An [E2B API key](https://e2b.dev/dashboard?tab=keys)
- A [Kernel API key](https://www.kernel.computer/)
- Python 3.10+ / Node.js 18+

<CodeGroup>
```bash JavaScript & TypeScript
npm i e2b @onkernel/sdk playwright-core
```
```bash Python
pip install e2b kernel playwright
```
</CodeGroup>

Set your keys in the environment:

```bash .env
E2B_API_KEY=e2b_***
KERNEL_API_KEY=kernel_***
```

E2B provides a pre-built sandbox template with the Kernel SDK and Playwright already installed:

| Template | What's included | Best for |
|---|---|---|
| `kernel-browser` | Kernel SDK, Playwright, Browser Use | Screenshots, scraping, app previews, autonomous agents |

## Examples

Here are three common patterns for using remote browsers with E2B sandboxes.

<CardGroup cols={3}>
<Card title="Screenshot app endpoints" icon="camera" href="#screenshot-app-endpoints">
Deploy a web app in a sandbox, screenshot every route
</Card>
<Card title="Agent data extraction" icon="robot" href="#agent-data-extraction">
Let an LLM autonomously browse and extract data
</Card>
<Card title="Live browser preview" icon="eye" href="#live-browser-preview">
Watch the browser in real time via Kernel's live view
</Card>
</CardGroup>

---

## Screenshot app endpoints

Deploy a web app inside an E2B sandbox, get a public URL, then use a Kernel browser to screenshot every route.

<Steps>
<Step title="Create the sandbox and start your app">

<CodeGroup>
```typescript JavaScript & TypeScript
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create('kernel-browser', {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure it's public

envs: { KERNEL_API_KEY: process.env.KERNEL_API_KEY! },
timeoutMs: 300_000,

Check warning on line 74 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L74

Did you really mean 'timeoutMs'?
})

await sandbox.files.write('/home/user/app.py', FASTAPI_APP)
await sandbox.commands.run(
'pip install --break-system-packages fastapi uvicorn',

Check warning on line 79 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L79

Did you really mean 'fastapi'?

Check warning on line 79 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L79

Did you really mean 'uvicorn'?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why --break-system-packages?

{ timeoutMs: 60_000 },

Check warning on line 80 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L80

Did you really mean 'timeoutMs'?
)
await sandbox.commands.run(
'uvicorn app:app --host 0.0.0.0 --port 8000',

Check warning on line 83 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L83

Did you really mean 'uvicorn'?
{ background: true, cwd: '/home/user' },
)
```
```python Python
import os
from e2b import Sandbox

sandbox = Sandbox.create(
"kernel-browser",
envs={"KERNEL_API_KEY": os.environ["KERNEL_API_KEY"]},
timeout=300,
)

sandbox.files.write("/home/user/app.py", FASTAPI_APP)
sandbox.commands.run(
"pip install --break-system-packages fastapi uvicorn",
timeout=60,
)
sandbox.commands.run(
"uvicorn app:app --host 0.0.0.0 --port 8000",
background=True,
cwd="/home/user",
)
```
</CodeGroup>
</Step>

<Step title="Screenshot each route with Kernel">
E2B exposes any sandbox port as a public HTTPS endpoint. Write a browsing script into the sandbox that creates a Kernel browser and screenshots each route.

<CodeGroup>
```typescript JavaScript & TypeScript
const host = sandbox.getHost(8000)
const appUrl = `https://${host}`

Check warning on line 117 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L117

Did you really mean 'appUrl'?

const BROWSE_SCRIPT = `
import sys
from kernel import Kernel
from playwright.sync_api import sync_playwright

app_url = "${appUrl}"

Check warning on line 124 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L124

Did you really mean 'app_url'?
routes = ["/", "/about", "/dashboard"]

kernel = Kernel()
kb = kernel.browsers.create()

with sync_playwright() as pw:

Check warning on line 130 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L130

Did you really mean 'pw'?
browser = pw.chromium.connect_over_cdp(kb.cdp_ws_url)
page = browser.new_page()
page.set_viewport_size({"width": 1280, "height": 720})

for route in routes:
page.goto(f"{app_url}{route}", wait_until="networkidle")
name = "home" if route == "/" else route.strip("/")
page.screenshot(path=f"/home/user/{name}.png")
print(f"Captured {route}")

browser.close()
`

await sandbox.files.write('/home/user/browse.py', BROWSE_SCRIPT)
const result = await sandbox.commands.run(
'python3 /home/user/browse.py',
{ timeoutMs: 60_000 },
)
console.log(result.stdout)
await sandbox.kill()
```
```python Python
host = sandbox.get_host(8000)
app_url = f"https://{host}"

BROWSE_SCRIPT = f'''
from kernel import Kernel
from playwright.sync_api import sync_playwright

app_url = "{app_url}"
routes = ["/", "/about", "/dashboard"]

kernel = Kernel()
kb = kernel.browsers.create()

with sync_playwright() as pw:
browser = pw.chromium.connect_over_cdp(kb.cdp_ws_url)
page = browser.new_page()
page.set_viewport_size({{"width": 1280, "height": 720}})

for route in routes:
page.goto(f"{{app_url}}{{route}}", wait_until="networkidle")
name = "home" if route == "/" else route.strip("/")
page.screenshot(path=f"/home/user/{{name}}.png")
print(f"Captured {{route}}")

browser.close()
'''

sandbox.files.write("/home/user/browse.py", BROWSE_SCRIPT)
result = sandbox.commands.run("python3 /home/user/browse.py", timeout=60)
print(result.stdout)
sandbox.kill()
```
</CodeGroup>
</Step>
</Steps>

---

## Agent data extraction

Use [Browser Use](https://docs.browser-use.com/) to let an LLM autonomously browse a website and extract data. The agent sees the page via screenshots and decides what to click, type, and navigate.

This requires an additional LLM API key:

```bash .env
ANTHROPIC_API_KEY=sk-ant-***
```

<Steps>
<Step title="Create the sandbox with API keys">

<CodeGroup>
```typescript JavaScript & TypeScript
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create('kernel-browser', {
envs: {
KERNEL_API_KEY: process.env.KERNEL_API_KEY!,
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
},
timeoutMs: 300_000,
})
```
```python Python
import os
from e2b import Sandbox

sandbox = Sandbox.create(
"kernel-browser",
envs={
"KERNEL_API_KEY": os.environ["KERNEL_API_KEY"],
"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"],
},
timeout=300,
)
```
</CodeGroup>
</Step>

<Step title="Write and run the agent">
The agent script runs inside the sandbox. It creates a Kernel browser, connects Browser Use, and completes the task autonomously.

<CodeGroup>
```typescript JavaScript & TypeScript
const AGENT_SCRIPT = `
import asyncio
from kernel import Kernel
from browser_use import Agent, Browser, ChatAnthropic

Check warning on line 240 in docs/use-cases/remote-browser.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/use-cases/remote-browser.mdx#L240

Did you really mean 'browser_use'?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you import the browser_use package but there's no installation?


async def main():
kernel = Kernel()
kb = kernel.browsers.create()
browser = Browser(cdp_url=kb.cdp_ws_url)

agent = Agent(
task="Go to https://news.ycombinator.com, find the top 5 stories, and return their titles and point counts as JSON",
llm=ChatAnthropic(model="claude-sonnet-4"),
browser=browser,
)
result = await agent.run()
print(result)

asyncio.run(main())
`

await sandbox.files.write('/home/user/agent_task.py', AGENT_SCRIPT)
const result = await sandbox.commands.run(
'python3 /home/user/agent_task.py',
{ timeoutMs: 180_000 },
)
console.log(result.stdout)
await sandbox.kill()
```
```python Python
AGENT_SCRIPT = '''
import asyncio
from kernel import Kernel
from browser_use import Agent, Browser, ChatAnthropic

async def main():
kernel = Kernel()
kb = kernel.browsers.create()
browser = Browser(cdp_url=kb.cdp_ws_url)

agent = Agent(
task="Go to https://news.ycombinator.com, find the top 5 stories, and return their titles and point counts as JSON",
llm=ChatAnthropic(model="claude-sonnet-4"),
browser=browser,
)
result = await agent.run()
print(result)

asyncio.run(main())
'''

sandbox.files.write("/home/user/agent_task.py", AGENT_SCRIPT)
result = sandbox.commands.run("python3 /home/user/agent_task.py", timeout=180)
print(result.stdout)
sandbox.kill()
```
</CodeGroup>
</Step>
</Steps>

---

## Live browser preview

Kernel provides a live view URL for every browser session — you can watch the browser in real time or embed it in your app. This is useful for debugging, demos, or letting users see what the agent is doing.

<CodeGroup>
```typescript JavaScript & TypeScript
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.create('kernel-browser', {
envs: { KERNEL_API_KEY: process.env.KERNEL_API_KEY! },
timeoutMs: 300_000,
})

const LIVE_VIEW_SCRIPT = `
from kernel import Kernel

kernel = Kernel()
browser = kernel.browsers.create()

# Print the live view URL — accessible from any browser
print(browser.browser_live_view_url)
`

await sandbox.files.write('/home/user/live_view.py', LIVE_VIEW_SCRIPT)
const result = await sandbox.commands.run(
'python3 /home/user/live_view.py',
{ timeoutMs: 30_000 },
)
const liveViewUrl = result.stdout.trim()
console.log('Watch the browser:', liveViewUrl)

// Embed in your app as an iframe
// <iframe src={liveViewUrl}></iframe>

// Read-only mode (no mouse/keyboard interaction)
// liveViewUrl + '?readOnly=true'
```
```python Python
import os
from e2b import Sandbox

sandbox = Sandbox.create(
"kernel-browser",
envs={"KERNEL_API_KEY": os.environ["KERNEL_API_KEY"]},
timeout=300,
)

LIVE_VIEW_SCRIPT = '''
from kernel import Kernel

kernel = Kernel()
browser = kernel.browsers.create()

# Print the live view URL — accessible from any browser
print(browser.browser_live_view_url)
'''

sandbox.files.write("/home/user/live_view.py", LIVE_VIEW_SCRIPT)
result = sandbox.commands.run("python3 /home/user/live_view.py", timeout=30)
live_view_url = result.stdout.strip()
print("Watch the browser:", live_view_url)

# Embed in your app as an iframe
# <iframe src={live_view_url}></iframe>

# Read-only mode (no mouse/keyboard interaction)
# live_view_url + '?readOnly=true'
```
</CodeGroup>

The live view URL stays active until the browser is deleted or times out. For more details, see the [Kernel live view documentation](https://www.kernel.sh/docs/browsers/live-view).

## Related guides

<CardGroup cols={3}>
<Card title="Computer use" icon="desktop" href="/docs/use-cases/computer-use">
Local browser automation with virtual desktops
</Card>
<Card title="Sandbox lifecycle" icon="rotate" href="/docs/sandbox">
Create, manage, and control sandbox lifecycle
</Card>
<Card title="Running commands" icon="terminal" href="/docs/commands">
Run terminal commands inside the sandbox
</Card>
</CardGroup>
Loading