open-browser-use-sdk 0.1.23__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,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: open-browser-use-sdk
3
+ Version: 0.1.23
4
+ Summary: Python SDK for Open Browser Use.
5
+ Author: iFurySt
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/iFurySt/open-codex-browser-use
8
+ Project-URL: Repository, https://github.com/iFurySt/open-codex-browser-use
9
+ Project-URL: Issues, https://github.com/iFurySt/open-codex-browser-use/issues
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Open Browser Use Python SDK
14
+
15
+ Python client for controlling a real Chrome profile through Open Browser Use.
16
+ The package distribution is `open-browser-use-sdk`; the import module remains
17
+ `open_browser_use`.
18
+
19
+ ## Installation
20
+
21
+ ```sh
22
+ pip install open-browser-use-sdk
23
+ ```
24
+
25
+ The SDK expects the `open-browser-use` CLI and Chrome extension to already be
26
+ installed and connected:
27
+
28
+ ```sh
29
+ open-browser-use ping
30
+ open-browser-use info
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```py
36
+ import json
37
+ from pathlib import Path
38
+
39
+ from open_browser_use import connect_open_browser_use
40
+
41
+ registry = json.loads(Path("/tmp/open-browser-use/active.json").read_text())
42
+
43
+ browser = connect_open_browser_use(
44
+ socket_path=registry["socketPath"],
45
+ session_id="python-sdk-example",
46
+ )
47
+
48
+ try:
49
+ browser.client.name_session("Python SDK example - OBU")
50
+ tab = browser.new_tab()
51
+ tab.goto("https://example.com", wait_until="domcontentloaded")
52
+ print(tab.title())
53
+ finally:
54
+ browser.client.finalize_tabs([])
55
+ browser.close()
56
+ ```
57
+
58
+ Use `OpenBrowserUseClient` directly when you need raw Browser Use JSON-RPC or
59
+ CDP methods.
@@ -0,0 +1,47 @@
1
+ # Open Browser Use Python SDK
2
+
3
+ Python client for controlling a real Chrome profile through Open Browser Use.
4
+ The package distribution is `open-browser-use-sdk`; the import module remains
5
+ `open_browser_use`.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ pip install open-browser-use-sdk
11
+ ```
12
+
13
+ The SDK expects the `open-browser-use` CLI and Chrome extension to already be
14
+ installed and connected:
15
+
16
+ ```sh
17
+ open-browser-use ping
18
+ open-browser-use info
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```py
24
+ import json
25
+ from pathlib import Path
26
+
27
+ from open_browser_use import connect_open_browser_use
28
+
29
+ registry = json.loads(Path("/tmp/open-browser-use/active.json").read_text())
30
+
31
+ browser = connect_open_browser_use(
32
+ socket_path=registry["socketPath"],
33
+ session_id="python-sdk-example",
34
+ )
35
+
36
+ try:
37
+ browser.client.name_session("Python SDK example - OBU")
38
+ tab = browser.new_tab()
39
+ tab.goto("https://example.com", wait_until="domcontentloaded")
40
+ print(tab.title())
41
+ finally:
42
+ browser.client.finalize_tabs([])
43
+ browser.close()
44
+ ```
45
+
46
+ Use `OpenBrowserUseClient` directly when you need raw Browser Use JSON-RPC or
47
+ CDP methods.
@@ -0,0 +1,19 @@
1
+ from .client import (
2
+ OpenBrowserUseBrowser,
3
+ OpenBrowserUseCdp,
4
+ OpenBrowserUseClient,
5
+ OpenBrowserUseLocator,
6
+ OpenBrowserUseTab,
7
+ OpenBrowserUseTabPlaywright,
8
+ connect_open_browser_use,
9
+ )
10
+
11
+ __all__ = [
12
+ "OpenBrowserUseBrowser",
13
+ "OpenBrowserUseCdp",
14
+ "OpenBrowserUseClient",
15
+ "OpenBrowserUseLocator",
16
+ "OpenBrowserUseTab",
17
+ "OpenBrowserUseTabPlaywright",
18
+ "connect_open_browser_use",
19
+ ]
@@ -0,0 +1,477 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import socket
5
+ import struct
6
+ import time
7
+ from dataclasses import dataclass
8
+ from typing import Any, Callable, Literal
9
+
10
+
11
+ JsonObject = dict[str, Any]
12
+ LoadState = Literal["domcontentloaded", "load"]
13
+ NotificationHandler = Callable[[JsonObject], None]
14
+ DEFAULT_NAVIGATION_TIMEOUT = 10.0
15
+
16
+
17
+ @dataclass
18
+ class OpenBrowserUseClient:
19
+ socket_path: str
20
+ session_id: str = "open-browser-use-python"
21
+ turn_id: str | None = None
22
+ timeout: float = 10.0
23
+
24
+ def __post_init__(self) -> None:
25
+ if self.turn_id is None:
26
+ self.turn_id = f"turn-{time.time_ns()}"
27
+ self._next_id = 1
28
+ self._socket: socket.socket | None = None
29
+ self._notification_handlers: list[NotificationHandler] = []
30
+
31
+ def connect(self) -> "OpenBrowserUseClient":
32
+ if self._socket is None:
33
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
34
+ sock.settimeout(self.timeout)
35
+ sock.connect(self.socket_path)
36
+ self._socket = sock
37
+ return self
38
+
39
+ def close(self) -> None:
40
+ if self._socket is not None:
41
+ self._socket.close()
42
+ self._socket = None
43
+
44
+ def on_notification(self, handler: NotificationHandler) -> Callable[[], None]:
45
+ self._notification_handlers.append(handler)
46
+
47
+ def remove() -> None:
48
+ if handler in self._notification_handlers:
49
+ self._notification_handlers.remove(handler)
50
+
51
+ return remove
52
+
53
+ def request(self, method: str, params: JsonObject | None = None) -> Any:
54
+ self.connect()
55
+ if self._socket is None:
56
+ raise RuntimeError("Open Browser Use socket is not connected")
57
+ request_id = self._next_id
58
+ self._next_id += 1
59
+ merged_params: JsonObject = {
60
+ "session_id": self.session_id,
61
+ "turn_id": self.turn_id,
62
+ }
63
+ if params:
64
+ merged_params.update(params)
65
+ request = {
66
+ "jsonrpc": "2.0",
67
+ "id": request_id,
68
+ "method": method,
69
+ "params": merged_params,
70
+ }
71
+ self._socket.sendall(encode_frame(request))
72
+ while True:
73
+ response = read_frame(self._socket)
74
+ if response.get("id") == request_id:
75
+ if "error" in response:
76
+ message = response["error"].get("message", "Open Browser Use request failed")
77
+ raise RuntimeError(message)
78
+ return response.get("result")
79
+ if "id" not in response and isinstance(response.get("method"), str):
80
+ self._dispatch_notification(response)
81
+ continue
82
+ raise RuntimeError(f"unexpected response id: {response.get('id')!r}")
83
+
84
+ def _dispatch_notification(self, notification: JsonObject) -> None:
85
+ for handler in list(self._notification_handlers):
86
+ handler(notification)
87
+
88
+ def get_info(self) -> Any:
89
+ return self.request("getInfo")
90
+
91
+ def create_tab(self) -> Any:
92
+ return self.request("createTab")
93
+
94
+ def get_tabs(self) -> Any:
95
+ return self.request("getTabs")
96
+
97
+ def get_user_tabs(self) -> Any:
98
+ return self.request("getUserTabs")
99
+
100
+ def get_user_history(self, **params: Any) -> Any:
101
+ return self.request("getUserHistory", params)
102
+
103
+ def claim_user_tab(self, tab_id: int) -> Any:
104
+ return self.request("claimUserTab", {"tabId": tab_id})
105
+
106
+ def finalize_tabs(self, keep: list[JsonObject]) -> Any:
107
+ return self.request("finalizeTabs", {"keep": keep})
108
+
109
+ def name_session(self, name: str) -> Any:
110
+ return self.request("nameSession", {"name": name})
111
+
112
+ def attach(self, tab_id: int) -> Any:
113
+ return self.request("attach", {"tabId": tab_id})
114
+
115
+ def detach(self, tab_id: int) -> Any:
116
+ return self.request("detach", {"tabId": tab_id})
117
+
118
+ def execute_cdp(self, tab_id: int, method: str, command_params: JsonObject | None = None) -> Any:
119
+ return self.request(
120
+ "executeCdp",
121
+ {
122
+ "target": {"tabId": tab_id},
123
+ "method": method,
124
+ "commandParams": command_params or {},
125
+ },
126
+ )
127
+
128
+ def move_mouse(self, tab_id: int, x: float, y: float, wait_for_arrival: bool = True) -> Any:
129
+ return self.request(
130
+ "moveMouse",
131
+ {
132
+ "tabId": tab_id,
133
+ "x": x,
134
+ "y": y,
135
+ "waitForArrival": wait_for_arrival,
136
+ },
137
+ )
138
+
139
+ def wait_for_file_chooser(self, tab_id: int, timeout_ms: int | None = None) -> Any:
140
+ params: JsonObject = {"tabId": tab_id}
141
+ if timeout_ms is not None:
142
+ params["timeoutMs"] = timeout_ms
143
+ return self.request("waitForFileChooser", params)
144
+
145
+ def set_file_chooser_files(self, file_chooser_id: str, files: list[str]) -> Any:
146
+ return self.request(
147
+ "setFileChooserFiles",
148
+ {
149
+ "fileChooserId": file_chooser_id,
150
+ "files": files,
151
+ },
152
+ )
153
+
154
+ def wait_for_download(self, tab_id: int, timeout_ms: int | None = None) -> Any:
155
+ params: JsonObject = {"tabId": tab_id}
156
+ if timeout_ms is not None:
157
+ params["timeoutMs"] = timeout_ms
158
+ return self.request("waitForDownload", params)
159
+
160
+ def download_path(self, download_id: str, timeout_ms: int | None = None) -> Any:
161
+ params: JsonObject = {"downloadId": download_id}
162
+ if timeout_ms is not None:
163
+ params["timeoutMs"] = timeout_ms
164
+ return self.request("downloadPath", params)
165
+
166
+ def browser_user_history(self, **params: Any) -> Any:
167
+ return self.get_user_history(**params)
168
+
169
+ def read_clipboard_text(self, tab_id: int) -> Any:
170
+ return self.request("readClipboardText", {"tabId": tab_id})
171
+
172
+ def write_clipboard_text(self, tab_id: int, text: str) -> Any:
173
+ return self.request("writeClipboardText", {"tabId": tab_id, "text": text})
174
+
175
+ def read_clipboard(self, tab_id: int) -> Any:
176
+ return self.request("readClipboard", {"tabId": tab_id})
177
+
178
+ def write_clipboard(self, tab_id: int, items: list[JsonObject]) -> Any:
179
+ return self.request("writeClipboard", {"tabId": tab_id, "items": items})
180
+
181
+ def turn_ended(self) -> Any:
182
+ return self.request("turnEnded")
183
+
184
+
185
+ def connect_open_browser_use(
186
+ socket_path: str,
187
+ session_id: str = "open-browser-use-python",
188
+ turn_id: str | None = None,
189
+ timeout: float = 10.0,
190
+ ) -> "OpenBrowserUseBrowser":
191
+ browser = OpenBrowserUseBrowser(
192
+ OpenBrowserUseClient(
193
+ socket_path=socket_path,
194
+ session_id=session_id,
195
+ turn_id=turn_id,
196
+ timeout=timeout,
197
+ )
198
+ )
199
+ browser.connect()
200
+ return browser
201
+
202
+
203
+ class OpenBrowserUseBrowser:
204
+ def __init__(self, client: OpenBrowserUseClient) -> None:
205
+ self.client = client
206
+ self.cdp = OpenBrowserUseCdp(client)
207
+
208
+ def connect(self) -> "OpenBrowserUseBrowser":
209
+ self.client.connect()
210
+ return self
211
+
212
+ def close(self) -> None:
213
+ self.client.close()
214
+
215
+ def new_tab(
216
+ self,
217
+ url: str | None = None,
218
+ wait_until: LoadState = "load",
219
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
220
+ ) -> "OpenBrowserUseTab":
221
+ result = self.client.create_tab()
222
+ tab = self.tab(_tab_id_from_value(result, "create_tab response"))
223
+ if url:
224
+ tab.goto(url, wait_until=wait_until, timeout=timeout)
225
+ return tab
226
+
227
+ def tab(self, tab_id: int) -> "OpenBrowserUseTab":
228
+ return OpenBrowserUseTab(self, tab_id)
229
+
230
+ def get_tabs(self) -> Any:
231
+ return self.client.get_tabs()
232
+
233
+
234
+ class OpenBrowserUseTab:
235
+ def __init__(self, browser: OpenBrowserUseBrowser, tab_id: int) -> None:
236
+ self.browser = browser
237
+ self.id = tab_id
238
+ self.playwright = OpenBrowserUseTabPlaywright(self)
239
+
240
+ def goto(
241
+ self,
242
+ url: str,
243
+ wait_until: LoadState = "load",
244
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
245
+ ) -> Any:
246
+ return self.browser.cdp.navigate(self.id, url, wait_until=wait_until, timeout=timeout)
247
+
248
+ def wait_for_load_state(
249
+ self,
250
+ state: LoadState = "load",
251
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
252
+ ) -> None:
253
+ self.browser.cdp.wait_for_load_state(self.id, state=state, timeout=timeout)
254
+
255
+ def dom_snapshot(self) -> str:
256
+ value = self.browser.cdp.evaluate(self.id, "document.body?.innerText ?? ''")
257
+ return "" if value is None else str(value)
258
+
259
+ def evaluate(self, expression: str, await_promise: bool | None = None) -> Any:
260
+ return self.browser.cdp.evaluate(self.id, expression, await_promise=await_promise)
261
+
262
+ def title(self) -> str:
263
+ value = self.evaluate("document.title ?? ''")
264
+ return "" if value is None else str(value)
265
+
266
+ def url(self) -> str:
267
+ value = self.evaluate("location.href")
268
+ return "" if value is None else str(value)
269
+
270
+ def wait_for_timeout(self, timeout_ms: float) -> None:
271
+ if timeout_ms < 0:
272
+ raise ValueError("timeout_ms must be non-negative")
273
+ time.sleep(timeout_ms / 1000)
274
+
275
+ def locator(self, selector: str) -> "OpenBrowserUseLocator":
276
+ return OpenBrowserUseLocator(self, selector)
277
+
278
+ def close(self) -> Any:
279
+ return self.browser.cdp.call(self.id, "Page.close")
280
+
281
+
282
+ class OpenBrowserUseTabPlaywright:
283
+ def __init__(self, tab: OpenBrowserUseTab) -> None:
284
+ self.tab = tab
285
+
286
+ def wait_for_load_state(
287
+ self,
288
+ state: LoadState = "load",
289
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
290
+ ) -> None:
291
+ self.tab.wait_for_load_state(state=state, timeout=timeout)
292
+
293
+ def dom_snapshot(self) -> str:
294
+ return self.tab.dom_snapshot()
295
+
296
+ def title(self) -> str:
297
+ return self.tab.title()
298
+
299
+ def url(self) -> str:
300
+ return self.tab.url()
301
+
302
+ def wait_for_timeout(self, timeout_ms: float) -> None:
303
+ self.tab.wait_for_timeout(timeout_ms)
304
+
305
+ def locator(self, selector: str) -> "OpenBrowserUseLocator":
306
+ return self.tab.locator(selector)
307
+
308
+
309
+ class OpenBrowserUseLocator:
310
+ def __init__(self, tab: OpenBrowserUseTab, selector: str) -> None:
311
+ if not selector:
312
+ raise ValueError("locator requires a selector")
313
+ self.tab = tab
314
+ self.selector = selector
315
+
316
+ def inner_text(self, timeout_ms: int | None = None) -> str:
317
+ value = self.tab.evaluate(
318
+ _locator_inner_text_expression(self.selector, timeout_ms),
319
+ await_promise=True,
320
+ )
321
+ return "" if value is None else str(value)
322
+
323
+
324
+ class OpenBrowserUseCdp:
325
+ def __init__(self, client: OpenBrowserUseClient) -> None:
326
+ self.client = client
327
+ self._attached_tab_ids: set[int] = set()
328
+
329
+ def call(
330
+ self,
331
+ tab_id: int,
332
+ method: str,
333
+ command_params: JsonObject | None = None,
334
+ timeout_ms: int | None = None,
335
+ ) -> Any:
336
+ self.ensure_attached(tab_id)
337
+ params: JsonObject = {
338
+ "target": {"tabId": tab_id},
339
+ "method": method,
340
+ "commandParams": command_params or {},
341
+ }
342
+ if timeout_ms is not None:
343
+ params["timeoutMs"] = timeout_ms
344
+ return self.client.request("executeCdp", params)
345
+
346
+ def evaluate(self, tab_id: int, expression: str, await_promise: bool | None = None) -> Any:
347
+ command_params: JsonObject = {
348
+ "expression": expression,
349
+ "returnByValue": True,
350
+ }
351
+ if await_promise is not None:
352
+ command_params["awaitPromise"] = await_promise
353
+ result = self.call(tab_id, "Runtime.evaluate", command_params)
354
+ if isinstance(result, dict) and isinstance(result.get("exceptionDetails"), dict):
355
+ raise RuntimeError(str(result["exceptionDetails"].get("text", "Open Browser Use evaluation failed")))
356
+ if isinstance(result, dict) and isinstance(result.get("result"), dict):
357
+ return result["result"].get("value")
358
+ return None
359
+
360
+ def navigate(
361
+ self,
362
+ tab_id: int,
363
+ url: str,
364
+ wait_until: LoadState = "load",
365
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
366
+ ) -> Any:
367
+ if not url:
368
+ raise ValueError("goto requires a URL")
369
+ _assert_supported_load_state(wait_until)
370
+ self.call(tab_id, "Page.enable")
371
+ result = self.call(tab_id, "Page.navigate", {"url": url}, timeout_ms=int(timeout * 1000))
372
+ if isinstance(result, dict) and result.get("errorText"):
373
+ raise RuntimeError(f"Browser failed to navigate tab {tab_id}: {result['errorText']}")
374
+ self.wait_for_load_state(tab_id, state=wait_until, timeout=timeout)
375
+ return result
376
+
377
+ def wait_for_load_state(
378
+ self,
379
+ tab_id: int,
380
+ state: LoadState = "load",
381
+ timeout: float = DEFAULT_NAVIGATION_TIMEOUT,
382
+ ) -> None:
383
+ _assert_supported_load_state(state)
384
+ self.call(tab_id, "Page.enable")
385
+ deadline = time.monotonic() + timeout
386
+ while True:
387
+ if _document_state_matches(self.read_document_state(tab_id), state):
388
+ return
389
+ if time.monotonic() >= deadline:
390
+ raise TimeoutError(f"Timed out waiting for {state} in tab {tab_id}")
391
+ time.sleep(0.1)
392
+
393
+ def read_document_state(self, tab_id: int) -> JsonObject | None:
394
+ try:
395
+ value = self.evaluate(tab_id, "({ href: window.location.href, readyState: document.readyState })")
396
+ except Exception:
397
+ return None
398
+ return value if isinstance(value, dict) else None
399
+
400
+ def ensure_attached(self, tab_id: int) -> None:
401
+ if tab_id in self._attached_tab_ids:
402
+ return
403
+ self.client.attach(tab_id)
404
+ self._attached_tab_ids.add(tab_id)
405
+
406
+
407
+ def encode_frame(value: JsonObject) -> bytes:
408
+ payload = json.dumps(value, separators=(",", ":")).encode("utf-8")
409
+ return struct.pack(_native_u32(), len(payload)) + payload
410
+
411
+
412
+ def read_frame(sock: socket.socket) -> JsonObject:
413
+ header = _read_exact(sock, 4)
414
+ (length,) = struct.unpack(_native_u32(), header)
415
+ payload = _read_exact(sock, length)
416
+ value = json.loads(payload.decode("utf-8"))
417
+ if not isinstance(value, dict):
418
+ raise RuntimeError("Open Browser Use response must be a JSON object")
419
+ return value
420
+
421
+
422
+ def _read_exact(sock: socket.socket, length: int) -> bytes:
423
+ chunks: list[bytes] = []
424
+ remaining = length
425
+ while remaining > 0:
426
+ chunk = sock.recv(remaining)
427
+ if not chunk:
428
+ raise EOFError("Open Browser Use socket closed")
429
+ chunks.append(chunk)
430
+ remaining -= len(chunk)
431
+ return b"".join(chunks)
432
+
433
+
434
+ def _native_u32() -> str:
435
+ return "=I"
436
+
437
+
438
+ def _tab_id_from_value(value: Any, label: str) -> int:
439
+ if not isinstance(value, dict):
440
+ raise RuntimeError(f"{label} did not include a tab object")
441
+ tab_id = value.get("id")
442
+ if isinstance(tab_id, int) and tab_id > 0:
443
+ return tab_id
444
+ if isinstance(tab_id, str) and tab_id.isdigit() and int(tab_id) > 0:
445
+ return int(tab_id)
446
+ raise RuntimeError(f"{label} did not include a numeric tab id")
447
+
448
+
449
+ def _assert_supported_load_state(state: str) -> None:
450
+ if state not in ("domcontentloaded", "load"):
451
+ raise ValueError(f'Unsupported load state "{state}". Use "domcontentloaded" or "load".')
452
+
453
+
454
+ def _document_state_matches(document_state: JsonObject | None, state: LoadState) -> bool:
455
+ ready_state = document_state.get("readyState") if isinstance(document_state, dict) else None
456
+ return ready_state == "complete" or (state == "domcontentloaded" and ready_state == "interactive")
457
+
458
+
459
+ def _locator_inner_text_expression(selector: str, timeout_ms: int | None) -> str:
460
+ timeout = DEFAULT_NAVIGATION_TIMEOUT * 1000 if timeout_ms is None else timeout_ms
461
+ if timeout < 0:
462
+ raise ValueError("timeout_ms must be non-negative")
463
+ selector_json = json.dumps(selector)
464
+ return f"""(async () => {{
465
+ const selector = {selector_json};
466
+ const deadline = performance.now() + {timeout};
467
+ while (true) {{
468
+ const element = document.querySelector(selector);
469
+ if (element) {{
470
+ return element.innerText ?? element.textContent ?? "";
471
+ }}
472
+ if (performance.now() >= deadline) {{
473
+ throw new Error(`Timed out waiting for locator ${{selector}}`);
474
+ }}
475
+ await new Promise((resolve) => setTimeout(resolve, 100));
476
+ }}
477
+ }})()"""
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: open-browser-use-sdk
3
+ Version: 0.1.23
4
+ Summary: Python SDK for Open Browser Use.
5
+ Author: iFurySt
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/iFurySt/open-codex-browser-use
8
+ Project-URL: Repository, https://github.com/iFurySt/open-codex-browser-use
9
+ Project-URL: Issues, https://github.com/iFurySt/open-codex-browser-use/issues
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Open Browser Use Python SDK
14
+
15
+ Python client for controlling a real Chrome profile through Open Browser Use.
16
+ The package distribution is `open-browser-use-sdk`; the import module remains
17
+ `open_browser_use`.
18
+
19
+ ## Installation
20
+
21
+ ```sh
22
+ pip install open-browser-use-sdk
23
+ ```
24
+
25
+ The SDK expects the `open-browser-use` CLI and Chrome extension to already be
26
+ installed and connected:
27
+
28
+ ```sh
29
+ open-browser-use ping
30
+ open-browser-use info
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```py
36
+ import json
37
+ from pathlib import Path
38
+
39
+ from open_browser_use import connect_open_browser_use
40
+
41
+ registry = json.loads(Path("/tmp/open-browser-use/active.json").read_text())
42
+
43
+ browser = connect_open_browser_use(
44
+ socket_path=registry["socketPath"],
45
+ session_id="python-sdk-example",
46
+ )
47
+
48
+ try:
49
+ browser.client.name_session("Python SDK example - OBU")
50
+ tab = browser.new_tab()
51
+ tab.goto("https://example.com", wait_until="domcontentloaded")
52
+ print(tab.title())
53
+ finally:
54
+ browser.client.finalize_tabs([])
55
+ browser.close()
56
+ ```
57
+
58
+ Use `OpenBrowserUseClient` directly when you need raw Browser Use JSON-RPC or
59
+ CDP methods.
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ open_browser_use/__init__.py
4
+ open_browser_use/client.py
5
+ open_browser_use_sdk.egg-info/PKG-INFO
6
+ open_browser_use_sdk.egg-info/SOURCES.txt
7
+ open_browser_use_sdk.egg-info/dependency_links.txt
8
+ open_browser_use_sdk.egg-info/top_level.txt
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "open-browser-use-sdk"
3
+ version = "0.1.23"
4
+ description = "Python SDK for Open Browser Use."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = "MIT"
8
+ authors = [
9
+ { name = "iFurySt" }
10
+ ]
11
+
12
+ [project.urls]
13
+ Homepage = "https://github.com/iFurySt/open-codex-browser-use"
14
+ Repository = "https://github.com/iFurySt/open-codex-browser-use"
15
+ Issues = "https://github.com/iFurySt/open-codex-browser-use/issues"
16
+
17
+ [tool.setuptools.packages.find]
18
+ where = ["."]
19
+ include = ["open_browser_use*"]
20
+
21
+ [build-system]
22
+ requires = ["setuptools>=77", "wheel"]
23
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+