You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<imgsrc="./assets/cloud-banner-python.png"alt="Browser Use Python"width="full"/>
1
+
<imgsrc="https://raw.githubusercontent.com/browser-use/browser-use-python/refs/heads/main/assets/cloud-banner-python.png"alt="Browser Use Python"width="full"/>
> The full API of this library can be found in [api.md](api.md).
28
28
29
-
## Async usage
30
-
31
-
Simply import `AsyncBrowserUse` instead of `BrowserUse` and use `await` with each API call:
32
-
33
-
```python
34
-
import os
35
-
import asyncio
36
-
from browser_use_sdk import AsyncBrowserUse
37
-
38
-
client = AsyncBrowserUse(
39
-
api_key=os.environ.get("BROWSER_USE_API_KEY"), # This is the default and can be omitted
40
-
)
41
-
42
-
43
-
asyncdefmain() -> None:
44
-
task =await client.tasks.run(
45
-
task="Search for the top 10 Hacker News posts and return the title and url.",
46
-
)
47
-
print(task.done_output)
48
-
49
-
50
-
asyncio.run(main())
51
-
```
52
-
53
-
Functionality between the synchronous and asynchronous clients is otherwise identical.
54
-
55
-
### With aiohttp
56
-
57
-
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
58
-
59
-
You can enable this by installing `aiohttp`:
60
-
61
-
```sh
62
-
# install from PyPI
63
-
pip install browser-use-sdk[aiohttp]
64
-
```
65
-
66
-
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
67
-
68
-
```python
69
-
import asyncio
70
-
from browser_use_sdk import DefaultAioHttpClient
71
-
from browser_use_sdk import AsyncBrowserUse
72
-
73
-
74
-
asyncdefmain() -> None:
75
-
asyncwith AsyncBrowserUse(
76
-
api_key="My API Key",
77
-
http_client=DefaultAioHttpClient(),
78
-
) as client:
79
-
task =await client.tasks.run(
80
-
task="Search for the top 10 Hacker News posts and return the title and url.",
81
-
)
82
-
print(task.done_output)
83
-
84
-
85
-
asyncio.run(main())
86
-
```
87
-
88
29
## Structured Output with Pydantic
89
30
90
31
Browser Use Python SDK provides first class support for Pydantic models.
@@ -115,6 +56,10 @@ asyncio.run(main())
115
56
116
57
## Streaming Updates with Async Iterators
117
58
59
+
> When presenting a long running task you might want to show updates as they happen.
60
+
61
+
Browser Use SDK exposes a `.stream` method that lets you subscribe to a sync or an async generator that automatically polls Browser Use Cloud servers and emits a new event when an update happens (e.g., live url becomes available, agent takes a new step, or agent completes the task).
62
+
118
63
```py
119
64
classHackerNewsPost(BaseModel):
120
65
title: str
@@ -132,7 +77,7 @@ async def main() -> None:
132
77
structured_output_json=SearchResult,
133
78
)
134
79
135
-
asyncfor update in client.tasks.stream(structured_task.id, structured_output_json=SearchResult):
80
+
asyncfor update in client.tasks.stream(task.id, structured_output_json=SearchResult):
Simply import `AsyncBrowserUse` instead of `BrowserUse` and use `await` with each API call:
145
+
146
+
```python
147
+
import os
148
+
import asyncio
149
+
from browser_use_sdk import AsyncBrowserUse
150
+
151
+
client = AsyncBrowserUse(
152
+
api_key=os.environ.get("BROWSER_USE_API_KEY"), # This is the default and can be omitted
153
+
)
154
+
155
+
156
+
asyncdefmain() -> None:
157
+
task =await client.tasks.run(
158
+
task="Search for the top 10 Hacker News posts and return the title and url.",
159
+
)
160
+
print(task.done_output)
161
+
162
+
163
+
asyncio.run(main())
164
+
```
165
+
166
+
Functionality between the synchronous and asynchronous clients is otherwise identical.
167
+
168
+
### With aiohttp
169
+
170
+
By default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.
171
+
172
+
You can enable this by installing `aiohttp`:
173
+
174
+
```sh
175
+
# install from PyPI
176
+
pip install browser-use-sdk[aiohttp]
177
+
```
178
+
179
+
Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
180
+
181
+
```python
182
+
import asyncio
183
+
from browser_use_sdk import DefaultAioHttpClient
184
+
from browser_use_sdk import AsyncBrowserUse
185
+
186
+
187
+
asyncdefmain() -> None:
188
+
asyncwith AsyncBrowserUse(
189
+
api_key="My API Key",
190
+
http_client=DefaultAioHttpClient(),
191
+
) as client:
192
+
task =await client.tasks.run(
193
+
task="Search for the top 10 Hacker News posts and return the title and url.",
194
+
)
195
+
print(task.done_output)
196
+
197
+
198
+
asyncio.run(main())
199
+
```
200
+
201
+
## Advanced
202
+
155
203
## Handling errors
156
204
157
205
When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `browser_use_sdk.APIConnectionError` is raised.
@@ -247,8 +295,6 @@ On timeout, an `APITimeoutError` is thrown.
247
295
248
296
Note that requests that time out are [retried twice by default](#retries).
249
297
250
-
## Advanced
251
-
252
298
### Logging
253
299
254
300
We use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.
@@ -294,58 +340,6 @@ These methods return an [`APIResponse`](https://github.com/browser-use/browser-u
294
340
295
341
The async client returns an [`AsyncAPIResponse`](https://github.com/browser-use/browser-use-python/tree/main/src/browser_use_sdk/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.
296
342
297
-
#### `.with_streaming_response`
298
-
299
-
The above interface eagerly reads the full response body when you make the request, which may not always be what you want.
300
-
301
-
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.
302
-
303
-
```python
304
-
with client.tasks.with_streaming_response.create(
305
-
task="Search for the top 10 Hacker News posts and return the title and url.",
306
-
) as response:
307
-
print(response.headers.get("X-My-Header"))
308
-
309
-
for line in response.iter_lines():
310
-
print(line)
311
-
```
312
-
313
-
The context manager is required so that the response will reliably be closed.
314
-
315
-
### Making custom/undocumented requests
316
-
317
-
This library is typed for convenient access to the documented API.
318
-
319
-
If you need to access undocumented endpoints, params, or response properties, the library can still be used.
320
-
321
-
#### Undocumented endpoints
322
-
323
-
To make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other
324
-
http verbs. Options on the client will be respected (such as retries) when making this request.
325
-
326
-
```py
327
-
import httpx
328
-
329
-
response = client.post(
330
-
"/foo",
331
-
cast_to=httpx.Response,
332
-
body={"my_param": True},
333
-
)
334
-
335
-
print(response.headers.get("x-foo"))
336
-
```
337
-
338
-
#### Undocumented request params
339
-
340
-
If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request
341
-
options.
342
-
343
-
#### Undocumented response properties
344
-
345
-
To access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You
346
-
can also get all the extra fields on the Pydantic model as a dict with
You can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:
@@ -388,29 +382,6 @@ with BrowserUse() as client:
388
382
# HTTP client is now closed
389
383
```
390
384
391
-
## Versioning
392
-
393
-
This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
394
-
395
-
1. Changes that only affect static types, without breaking runtime behavior.
396
-
2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
397
-
3. Changes that we do not expect to impact the vast majority of users in practice.
398
-
399
-
We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
400
-
401
-
We are keen for your feedback; please open an [issue](https://www.github.com/browser-use/browser-use-python/issues) with questions, bugs, or suggestions.
402
-
403
-
### Determining the installed version
404
-
405
-
If you've upgraded to the latest version but aren't seeing any new features you were expecting then your python environment is likely still using an older version.
406
-
407
-
You can determine the version that is being used at runtime with:
0 commit comments