orb-browser 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: orb-browser
3
+ Version: 0.1.0
4
+ Summary: Browser agents that sleep for $0 and wake in 500ms on Orb Cloud
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/nextbysam/orb-browser
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: license-file
15
+
16
+ # orb-browser
17
+
18
+ Browser agents that sleep for $0 and wake in 500ms.
19
+
20
+ Deploy headless Chrome on [Orb Cloud](https://orbcloud.dev). Connect [browser-use](https://github.com/browser-use/browser-use) or any CDP client. When idle, checkpoint the browser to NVMe — cookies, DOM, localStorage, everything preserved. Wake it up later in ~500ms, exactly where you left off.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install orb-browser browser-use
26
+ ```
27
+
28
+ Or from source:
29
+ ```bash
30
+ pip install git+https://github.com/nextbysam/orb-browser.git
31
+ ```
32
+
33
+ ## Get an API Key
34
+
35
+ ```bash
36
+ # Register
37
+ curl -X POST https://api.orbcloud.dev/api/v1/auth/register \
38
+ -H 'Content-Type: application/json' \
39
+ -d '{"email":"you@example.com"}'
40
+
41
+ # Create org key
42
+ curl -X POST https://api.orbcloud.dev/v1/keys \
43
+ -H "Authorization: Bearer YOUR_API_KEY" \
44
+ -H 'Content-Type: application/json' \
45
+ -d '{"name":"my-key"}'
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ```python
51
+ import asyncio
52
+ from orb_browser import OrbBrowser
53
+ from browser_use import Browser
54
+
55
+ async def main():
56
+ # Deploy a browser on Orb Cloud (~1-3 min first time)
57
+ orb = OrbBrowser(api_key="orb_...")
58
+ cdp_url = orb.deploy()
59
+
60
+ # Connect browser-use
61
+ browser = Browser(cdp_url=cdp_url)
62
+ await browser.start()
63
+
64
+ # Full browser control
65
+ await browser.navigate_to("https://example.com")
66
+ title = await browser.get_current_page_title()
67
+ screenshot = await browser.take_screenshot()
68
+
69
+ # Disconnect before sleep
70
+ await browser.stop()
71
+
72
+ # Sleep — frozen to NVMe, $0/hr
73
+ orb.sleep()
74
+
75
+ # ... hours later ...
76
+
77
+ # Wake — ~500ms, everything restored
78
+ cdp_url = orb.wake()
79
+
80
+ # Reconnect — same page, same cookies
81
+ browser = Browser(cdp_url=cdp_url)
82
+ await browser.start()
83
+
84
+ # Clean up
85
+ await browser.stop()
86
+ orb.destroy()
87
+
88
+ asyncio.run(main())
89
+ ```
90
+
91
+ ## API
92
+
93
+ ```python
94
+ from orb_browser import OrbBrowser
95
+
96
+ orb = OrbBrowser(api_key="orb_...")
97
+ ```
98
+
99
+ | Method | Description |
100
+ |--------|-------------|
101
+ | `orb.deploy()` | Deploy browser VM, returns CDP WebSocket URL |
102
+ | `orb.sleep()` | Checkpoint to NVMe ($0 while sleeping) |
103
+ | `orb.wake()` | Restore from checkpoint (~500ms), returns new CDP URL |
104
+ | `orb.destroy()` | Delete the VM |
105
+ | `orb.connect(computer_id, agent_port)` | Connect to existing VM |
106
+ | `orb.state` | Current state: init, deploying, running, sleeping, destroyed |
107
+ | `orb.vm_url` | HTTPS URL of the VM |
108
+ | `orb.cdp_url` | CDP WebSocket URL |
109
+
110
+ ## How It Works
111
+
112
+ 1. `deploy()` creates a VM on Orb Cloud, installs Chromium via Playwright, starts it with CDP debugging enabled
113
+ 2. Returns a `wss://` CDP URL that browser-use (or Puppeteer, Playwright, any CDP client) connects to
114
+ 3. `sleep()` calls CRIU to checkpoint the entire process tree (Node.js + Chromium + renderers) to NVMe
115
+ 4. `wake()` restores everything in ~500ms — the browser doesn't know it was frozen
116
+
117
+ ## Works With
118
+
119
+ - [browser-use](https://github.com/browser-use/browser-use) (78K stars) — AI browser agents
120
+ - [Playwright](https://playwright.dev) — `browser = await chromium.connect_over_cdp(cdp_url)`
121
+ - [Puppeteer](https://pptr.dev) — `browser = await puppeteer.connect({ browserWSEndpoint: cdpUrl })`
122
+ - Any CDP client
123
+
124
+ ## License
125
+
126
+ MIT
@@ -0,0 +1,111 @@
1
+ # orb-browser
2
+
3
+ Browser agents that sleep for $0 and wake in 500ms.
4
+
5
+ Deploy headless Chrome on [Orb Cloud](https://orbcloud.dev). Connect [browser-use](https://github.com/browser-use/browser-use) or any CDP client. When idle, checkpoint the browser to NVMe — cookies, DOM, localStorage, everything preserved. Wake it up later in ~500ms, exactly where you left off.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install orb-browser browser-use
11
+ ```
12
+
13
+ Or from source:
14
+ ```bash
15
+ pip install git+https://github.com/nextbysam/orb-browser.git
16
+ ```
17
+
18
+ ## Get an API Key
19
+
20
+ ```bash
21
+ # Register
22
+ curl -X POST https://api.orbcloud.dev/api/v1/auth/register \
23
+ -H 'Content-Type: application/json' \
24
+ -d '{"email":"you@example.com"}'
25
+
26
+ # Create org key
27
+ curl -X POST https://api.orbcloud.dev/v1/keys \
28
+ -H "Authorization: Bearer YOUR_API_KEY" \
29
+ -H 'Content-Type: application/json' \
30
+ -d '{"name":"my-key"}'
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```python
36
+ import asyncio
37
+ from orb_browser import OrbBrowser
38
+ from browser_use import Browser
39
+
40
+ async def main():
41
+ # Deploy a browser on Orb Cloud (~1-3 min first time)
42
+ orb = OrbBrowser(api_key="orb_...")
43
+ cdp_url = orb.deploy()
44
+
45
+ # Connect browser-use
46
+ browser = Browser(cdp_url=cdp_url)
47
+ await browser.start()
48
+
49
+ # Full browser control
50
+ await browser.navigate_to("https://example.com")
51
+ title = await browser.get_current_page_title()
52
+ screenshot = await browser.take_screenshot()
53
+
54
+ # Disconnect before sleep
55
+ await browser.stop()
56
+
57
+ # Sleep — frozen to NVMe, $0/hr
58
+ orb.sleep()
59
+
60
+ # ... hours later ...
61
+
62
+ # Wake — ~500ms, everything restored
63
+ cdp_url = orb.wake()
64
+
65
+ # Reconnect — same page, same cookies
66
+ browser = Browser(cdp_url=cdp_url)
67
+ await browser.start()
68
+
69
+ # Clean up
70
+ await browser.stop()
71
+ orb.destroy()
72
+
73
+ asyncio.run(main())
74
+ ```
75
+
76
+ ## API
77
+
78
+ ```python
79
+ from orb_browser import OrbBrowser
80
+
81
+ orb = OrbBrowser(api_key="orb_...")
82
+ ```
83
+
84
+ | Method | Description |
85
+ |--------|-------------|
86
+ | `orb.deploy()` | Deploy browser VM, returns CDP WebSocket URL |
87
+ | `orb.sleep()` | Checkpoint to NVMe ($0 while sleeping) |
88
+ | `orb.wake()` | Restore from checkpoint (~500ms), returns new CDP URL |
89
+ | `orb.destroy()` | Delete the VM |
90
+ | `orb.connect(computer_id, agent_port)` | Connect to existing VM |
91
+ | `orb.state` | Current state: init, deploying, running, sleeping, destroyed |
92
+ | `orb.vm_url` | HTTPS URL of the VM |
93
+ | `orb.cdp_url` | CDP WebSocket URL |
94
+
95
+ ## How It Works
96
+
97
+ 1. `deploy()` creates a VM on Orb Cloud, installs Chromium via Playwright, starts it with CDP debugging enabled
98
+ 2. Returns a `wss://` CDP URL that browser-use (or Puppeteer, Playwright, any CDP client) connects to
99
+ 3. `sleep()` calls CRIU to checkpoint the entire process tree (Node.js + Chromium + renderers) to NVMe
100
+ 4. `wake()` restores everything in ~500ms — the browser doesn't know it was frozen
101
+
102
+ ## Works With
103
+
104
+ - [browser-use](https://github.com/browser-use/browser-use) (78K stars) — AI browser agents
105
+ - [Playwright](https://playwright.dev) — `browser = await chromium.connect_over_cdp(cdp_url)`
106
+ - [Puppeteer](https://pptr.dev) — `browser = await puppeteer.connect({ browserWSEndpoint: cdpUrl })`
107
+ - Any CDP client
108
+
109
+ ## License
110
+
111
+ MIT
@@ -0,0 +1,4 @@
1
+ from orb_browser.client import OrbBrowser
2
+
3
+ __all__ = ["OrbBrowser"]
4
+ __version__ = "0.1.0"
@@ -0,0 +1,281 @@
1
+ """
2
+ OrbBrowser — deploy browser agents on Orb Cloud.
3
+
4
+ Usage:
5
+ from orb_browser import OrbBrowser
6
+
7
+ orb = OrbBrowser(api_key="orb_...")
8
+ cdp_url = orb.deploy()
9
+
10
+ # Use with browser-use
11
+ from browser_use import Browser
12
+ browser = Browser(cdp_url=cdp_url)
13
+ await browser.start()
14
+
15
+ # Sleep ($0 while frozen)
16
+ orb.sleep()
17
+
18
+ # Wake (~500ms)
19
+ cdp_url = orb.wake()
20
+ browser = Browser(cdp_url=cdp_url)
21
+ await browser.start()
22
+ """
23
+
24
+ import json
25
+ import time
26
+ import urllib.request
27
+ import urllib.error
28
+
29
+ # The orb.toml config that runs on Orb Cloud
30
+ ORB_TOML = """[agent]
31
+ name = "orb-browser"
32
+ lang = "node"
33
+ entry = "server.js"
34
+
35
+ [source]
36
+ git = "https://github.com/nextbysam/orb-browser.git"
37
+ branch = "main"
38
+
39
+ [build]
40
+ steps = [
41
+ "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libnss3 libatk-bridge2.0-0t64 libcups2t64 libdrm2 libgbm1 libpango-1.0-0 libcairo2 libasound2t64 libxshmfence1 libxcomposite1 libxrandr2 libxdamage1 libxfixes3 libxext6 libx11-xcb1 libxcb1 libxkbcommon0 libdbus-1-3",
42
+ "cd /agent/code && npm install",
43
+ "PLAYWRIGHT_BROWSERS_PATH=/opt/browsers npx playwright install chromium"
44
+ ]
45
+ working_dir = "/agent/code"
46
+
47
+ [agent.env]
48
+ PLAYWRIGHT_BROWSERS_PATH = "/opt/browsers"
49
+ PORT = "8000"
50
+ CDP_PORT = "9222"
51
+
52
+ [backend]
53
+ provider = "custom"
54
+
55
+ [ports]
56
+ expose = [8000, 9222]
57
+ """
58
+
59
+
60
+ class OrbBrowser:
61
+ """Deploy and manage a browser on Orb Cloud with sleep/wake support."""
62
+
63
+ def __init__(self, api_key: str, api_url: str = "https://api.orbcloud.dev"):
64
+ self.api_key = api_key
65
+ self.api_url = api_url
66
+ self.computer_id: str | None = None
67
+ self.short_id: str | None = None
68
+ self.agent_port: int | None = None
69
+ self.cdp_url: str | None = None
70
+ self._state = "init"
71
+
72
+ def deploy(
73
+ self,
74
+ name: str | None = None,
75
+ runtime_mb: int = 2048,
76
+ disk_mb: int = 4096,
77
+ wait: bool = True,
78
+ ) -> str:
79
+ """
80
+ Deploy a browser on Orb Cloud. Returns the CDP WebSocket URL.
81
+
82
+ Takes 1-3 minutes on first deploy (installs Chrome).
83
+ """
84
+ if name is None:
85
+ name = f"orb-browser-{int(time.time())}"
86
+
87
+ self._state = "deploying"
88
+ print(f"[orb-browser] Creating VM...")
89
+
90
+ # 1. Create computer
91
+ res = self._orb("POST", "/v1/computers", {
92
+ "name": name, "runtime_mb": runtime_mb, "disk_mb": disk_mb,
93
+ })
94
+ self.computer_id = res["id"]
95
+ self.short_id = self.computer_id[:8]
96
+ print(f"[orb-browser] VM: {self.short_id}")
97
+
98
+ try:
99
+ # 2. Upload config
100
+ req = urllib.request.Request(
101
+ f"{self.api_url}/v1/computers/{self.computer_id}/config",
102
+ data=ORB_TOML.encode(),
103
+ headers={
104
+ "Authorization": f"Bearer {self.api_key}",
105
+ "Content-Type": "application/toml",
106
+ },
107
+ method="POST",
108
+ )
109
+ urllib.request.urlopen(req)
110
+
111
+ # 3. Build
112
+ print(f"[orb-browser] Building (Chrome + Playwright)...")
113
+ req = urllib.request.Request(
114
+ f"{self.api_url}/v1/computers/{self.computer_id}/build",
115
+ headers={"Authorization": f"Bearer {self.api_key}"},
116
+ method="POST",
117
+ )
118
+ build_res = json.loads(urllib.request.urlopen(req, timeout=900).read())
119
+ if not build_res.get("success"):
120
+ failed = next(
121
+ (s for s in build_res.get("steps", []) if s["exit_code"] != 0),
122
+ None,
123
+ )
124
+ raise RuntimeError(f"Build failed: {failed}")
125
+ print(f"[orb-browser] Build OK")
126
+
127
+ # 4. Deploy agent
128
+ deploy_res = self._orb(
129
+ "POST", f"/v1/computers/{self.computer_id}/agents", {}
130
+ )
131
+ self.agent_port = deploy_res["agents"][0]["port"]
132
+
133
+ # 5. Wait for health
134
+ if wait:
135
+ self._wait_for_health(timeout=60)
136
+
137
+ # 6. Set hostname so CDP URLs are correct
138
+ vm_url = f"https://{self.short_id}.orbcloud.dev"
139
+ urllib.request.urlopen(
140
+ f"{vm_url}/set-host?host={self.short_id}.orbcloud.dev"
141
+ )
142
+
143
+ # 7. Get CDP URL
144
+ cdp_data = json.loads(
145
+ urllib.request.urlopen(f"{vm_url}/cdp").read()
146
+ )
147
+ self.cdp_url = cdp_data["cdpUrl"]
148
+ self._state = "running"
149
+
150
+ print(f"[orb-browser] Ready! CDP: {self.cdp_url}")
151
+ return self.cdp_url
152
+
153
+ except Exception:
154
+ self.destroy()
155
+ raise
156
+
157
+ def connect(self, computer_id: str, agent_port: int) -> str:
158
+ """Connect to an existing Orb Browser VM. Returns CDP URL."""
159
+ self.computer_id = computer_id
160
+ self.short_id = computer_id[:8]
161
+ self.agent_port = agent_port
162
+ self._state = "running"
163
+
164
+ vm_url = f"https://{self.short_id}.orbcloud.dev"
165
+ urllib.request.urlopen(
166
+ f"{vm_url}/set-host?host={self.short_id}.orbcloud.dev"
167
+ )
168
+ cdp_data = json.loads(urllib.request.urlopen(f"{vm_url}/cdp").read())
169
+ self.cdp_url = cdp_data["cdpUrl"]
170
+ return self.cdp_url
171
+
172
+ def sleep(self) -> dict:
173
+ """
174
+ Checkpoint the browser to NVMe. Costs $0 while sleeping.
175
+ WebSocket connections will drop — reconnect after wake().
176
+ """
177
+ if self._state != "running":
178
+ raise RuntimeError(f"Cannot sleep in state: {self._state}")
179
+
180
+ res = self._orb(
181
+ "POST",
182
+ f"/v1/computers/{self.computer_id}/agents/demote",
183
+ {"port": self.agent_port},
184
+ )
185
+ if res.get("status") != "demoted":
186
+ raise RuntimeError(f"Sleep failed: {res}")
187
+
188
+ self._state = "sleeping"
189
+ print(f"[orb-browser] Sleeping (frozen, $0)")
190
+ return res
191
+
192
+ def wake(self, wait: bool = True) -> str:
193
+ """
194
+ Restore the browser from NVMe. ~500ms.
195
+ Returns the CDP URL (same as before sleep).
196
+ Reconnect browser-use with the returned URL.
197
+ """
198
+ if self._state != "sleeping":
199
+ raise RuntimeError(f"Cannot wake in state: {self._state}")
200
+
201
+ res = self._orb(
202
+ "POST",
203
+ f"/v1/computers/{self.computer_id}/agents/promote",
204
+ {"port": self.agent_port},
205
+ )
206
+ if res.get("status") != "promoted":
207
+ raise RuntimeError(f"Wake failed: {res}")
208
+
209
+ if res.get("port"):
210
+ self.agent_port = res["port"]
211
+
212
+ if wait:
213
+ self._wait_for_health(timeout=30)
214
+
215
+ # Refresh CDP URL
216
+ vm_url = f"https://{self.short_id}.orbcloud.dev"
217
+ cdp_data = json.loads(urllib.request.urlopen(f"{vm_url}/cdp").read())
218
+ self.cdp_url = cdp_data["cdpUrl"]
219
+ self._state = "running"
220
+
221
+ print(f"[orb-browser] Awake! CDP: {self.cdp_url}")
222
+ return self.cdp_url
223
+
224
+ def destroy(self):
225
+ """Delete the VM."""
226
+ if not self.computer_id:
227
+ return
228
+ try:
229
+ req = urllib.request.Request(
230
+ f"{self.api_url}/v1/computers/{self.computer_id}",
231
+ headers={"Authorization": f"Bearer {self.api_key}"},
232
+ method="DELETE",
233
+ )
234
+ urllib.request.urlopen(req)
235
+ except urllib.error.HTTPError:
236
+ pass
237
+ self._state = "destroyed"
238
+ print(f"[orb-browser] Destroyed {self.short_id}")
239
+
240
+ @property
241
+ def vm_url(self) -> str | None:
242
+ return f"https://{self.short_id}.orbcloud.dev" if self.short_id else None
243
+
244
+ @property
245
+ def state(self) -> str:
246
+ return self._state
247
+
248
+ # -- Internal --
249
+
250
+ def _orb(self, method: str, path: str, body: dict | None = None) -> dict:
251
+ data = json.dumps(body).encode() if body is not None else None
252
+ req = urllib.request.Request(
253
+ f"{self.api_url}{path}",
254
+ data=data,
255
+ headers={
256
+ "Authorization": f"Bearer {self.api_key}",
257
+ "Content-Type": "application/json",
258
+ },
259
+ method=method,
260
+ )
261
+ try:
262
+ return json.loads(urllib.request.urlopen(req).read())
263
+ except urllib.error.HTTPError as e:
264
+ body_text = e.read().decode() if e.fp else ""
265
+ raise RuntimeError(
266
+ f"Orb API {method} {path} failed ({e.code}): {body_text}"
267
+ )
268
+
269
+ def _wait_for_health(self, timeout: int = 60):
270
+ vm_url = f"https://{self.short_id}.orbcloud.dev"
271
+ start = time.time()
272
+ while time.time() - start < timeout:
273
+ try:
274
+ res = urllib.request.urlopen(f"{vm_url}/health", timeout=5)
275
+ data = json.loads(res.read())
276
+ if data.get("status") == "ok" and data.get("browserReady"):
277
+ return
278
+ except Exception:
279
+ pass
280
+ time.sleep(2)
281
+ raise TimeoutError(f"Browser not ready after {timeout}s")
@@ -0,0 +1,126 @@
1
+ Metadata-Version: 2.4
2
+ Name: orb-browser
3
+ Version: 0.1.0
4
+ Summary: Browser agents that sleep for $0 and wake in 500ms on Orb Cloud
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/nextbysam/orb-browser
7
+ Classifier: Development Status :: 3 - Alpha
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Dynamic: license-file
15
+
16
+ # orb-browser
17
+
18
+ Browser agents that sleep for $0 and wake in 500ms.
19
+
20
+ Deploy headless Chrome on [Orb Cloud](https://orbcloud.dev). Connect [browser-use](https://github.com/browser-use/browser-use) or any CDP client. When idle, checkpoint the browser to NVMe — cookies, DOM, localStorage, everything preserved. Wake it up later in ~500ms, exactly where you left off.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install orb-browser browser-use
26
+ ```
27
+
28
+ Or from source:
29
+ ```bash
30
+ pip install git+https://github.com/nextbysam/orb-browser.git
31
+ ```
32
+
33
+ ## Get an API Key
34
+
35
+ ```bash
36
+ # Register
37
+ curl -X POST https://api.orbcloud.dev/api/v1/auth/register \
38
+ -H 'Content-Type: application/json' \
39
+ -d '{"email":"you@example.com"}'
40
+
41
+ # Create org key
42
+ curl -X POST https://api.orbcloud.dev/v1/keys \
43
+ -H "Authorization: Bearer YOUR_API_KEY" \
44
+ -H 'Content-Type: application/json' \
45
+ -d '{"name":"my-key"}'
46
+ ```
47
+
48
+ ## Usage
49
+
50
+ ```python
51
+ import asyncio
52
+ from orb_browser import OrbBrowser
53
+ from browser_use import Browser
54
+
55
+ async def main():
56
+ # Deploy a browser on Orb Cloud (~1-3 min first time)
57
+ orb = OrbBrowser(api_key="orb_...")
58
+ cdp_url = orb.deploy()
59
+
60
+ # Connect browser-use
61
+ browser = Browser(cdp_url=cdp_url)
62
+ await browser.start()
63
+
64
+ # Full browser control
65
+ await browser.navigate_to("https://example.com")
66
+ title = await browser.get_current_page_title()
67
+ screenshot = await browser.take_screenshot()
68
+
69
+ # Disconnect before sleep
70
+ await browser.stop()
71
+
72
+ # Sleep — frozen to NVMe, $0/hr
73
+ orb.sleep()
74
+
75
+ # ... hours later ...
76
+
77
+ # Wake — ~500ms, everything restored
78
+ cdp_url = orb.wake()
79
+
80
+ # Reconnect — same page, same cookies
81
+ browser = Browser(cdp_url=cdp_url)
82
+ await browser.start()
83
+
84
+ # Clean up
85
+ await browser.stop()
86
+ orb.destroy()
87
+
88
+ asyncio.run(main())
89
+ ```
90
+
91
+ ## API
92
+
93
+ ```python
94
+ from orb_browser import OrbBrowser
95
+
96
+ orb = OrbBrowser(api_key="orb_...")
97
+ ```
98
+
99
+ | Method | Description |
100
+ |--------|-------------|
101
+ | `orb.deploy()` | Deploy browser VM, returns CDP WebSocket URL |
102
+ | `orb.sleep()` | Checkpoint to NVMe ($0 while sleeping) |
103
+ | `orb.wake()` | Restore from checkpoint (~500ms), returns new CDP URL |
104
+ | `orb.destroy()` | Delete the VM |
105
+ | `orb.connect(computer_id, agent_port)` | Connect to existing VM |
106
+ | `orb.state` | Current state: init, deploying, running, sleeping, destroyed |
107
+ | `orb.vm_url` | HTTPS URL of the VM |
108
+ | `orb.cdp_url` | CDP WebSocket URL |
109
+
110
+ ## How It Works
111
+
112
+ 1. `deploy()` creates a VM on Orb Cloud, installs Chromium via Playwright, starts it with CDP debugging enabled
113
+ 2. Returns a `wss://` CDP URL that browser-use (or Puppeteer, Playwright, any CDP client) connects to
114
+ 3. `sleep()` calls CRIU to checkpoint the entire process tree (Node.js + Chromium + renderers) to NVMe
115
+ 4. `wake()` restores everything in ~500ms — the browser doesn't know it was frozen
116
+
117
+ ## Works With
118
+
119
+ - [browser-use](https://github.com/browser-use/browser-use) (78K stars) — AI browser agents
120
+ - [Playwright](https://playwright.dev) — `browser = await chromium.connect_over_cdp(cdp_url)`
121
+ - [Puppeteer](https://pptr.dev) — `browser = await puppeteer.connect({ browserWSEndpoint: cdpUrl })`
122
+ - Any CDP client
123
+
124
+ ## License
125
+
126
+ MIT
@@ -0,0 +1,9 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ orb_browser/__init__.py
5
+ orb_browser/client.py
6
+ orb_browser.egg-info/PKG-INFO
7
+ orb_browser.egg-info/SOURCES.txt
8
+ orb_browser.egg-info/dependency_links.txt
9
+ orb_browser.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ orb_browser
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "orb-browser"
7
+ version = "0.1.0"
8
+ description = "Browser agents that sleep for $0 and wake in 500ms on Orb Cloud"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ ]
18
+
19
+ [project.urls]
20
+ Homepage = "https://github.com/nextbysam/orb-browser"
21
+
22
+ [tool.setuptools.packages.find]
23
+ include = ["orb_browser*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+