|
1 | 1 | --- |
2 | 2 | id: browser-use |
3 | | -title: Use Browser Use |
| 3 | +title: Browser AI agents with Browser Use |
4 | 4 | description: Build an Apify Actor that automates a browser with an LLM agent using the Browser Use library. |
5 | 5 | --- |
6 | 6 |
|
7 | | -import CodeBlock from '@theme/CodeBlock'; |
8 | | -import Tabs from '@theme/Tabs'; |
9 | | -import TabItem from '@theme/TabItem'; |
| 7 | +import RunnableCodeBlock from '@site/src/components/RunnableCodeBlock'; |
10 | 8 |
|
11 | | -import BrowserUseMain from '!!raw-loader!./code/browser_use_project/my_actor/main.py'; |
12 | | -import BrowserUseAgent from '!!raw-loader!./code/browser_use_project/my_actor/agent.py'; |
13 | | -import BrowserUseEntrypoint from '!!raw-loader!./code/browser_use_project/my_actor/__main__.py'; |
14 | | -import BrowserUseDockerfile from '!!raw-loader!./code/browser_use_project/Dockerfile'; |
| 9 | +import BrowserUseExample from '!!raw-loader!roa-loader!./code/09_browser_use.py'; |
15 | 10 |
|
16 | | -In this guide, you'll learn how to use the [Browser Use](https://browser-use.com/) library in your Apify Actors. |
| 11 | +In this guide, you'll learn how to use the [Browser Use](https://browser-use.com/) library to drive a browser with an LLM agent in your Apify Actors. |
17 | 12 |
|
18 | 13 | ## Introduction |
19 | 14 |
|
@@ -41,62 +36,38 @@ Browser Use needs an LLM to drive the agent. You choose a provider wrapper, give |
41 | 36 | - **`ChatAnthropic`** - Anthropic Claude models such as `claude-sonnet-4-5` or `claude-haiku-4-5`. Reads the key from `ANTHROPIC_API_KEY`. |
42 | 37 | - **`ChatGoogle`** - Google Gemini models such as `gemini-2.5-flash`. Reads the key from `GOOGLE_API_KEY`. |
43 | 38 |
|
44 | | -The example Actor in this guide uses `ChatOpenAI`, but switching providers is a one-line change in `my_actor/agent.py`. More capable models generally complete tasks in fewer steps and more reliably, while smaller models are cheaper per step. |
| 39 | +The example Actor in this guide uses `ChatOpenAI`, but switching providers is a one-line change in `run_agent_task`. More capable models generally complete tasks in fewer steps and more reliably, while smaller models are cheaper per step. |
45 | 40 |
|
46 | 41 | Keep the API key out of the Actor input and source code. The example reads it from an environment variable, which on the Apify platform you set as a [secret environment variable](https://docs.apify.com/platform/actors/development/programming-interface/environment-variables) (for example `OPENAI_API_KEY`), and locally you export in your shell. |
47 | 42 |
|
48 | 43 | ## Example Actor |
49 | 44 |
|
50 | 45 | The following Actor runs a Browser Use agent for a single task and stores its structured result in the default dataset. By default it opens [Hacker News](https://news.ycombinator.com) and returns the title and URL of the top five posts, but the task, model, and step limit are all configurable through the Actor input. |
51 | 46 |
|
52 | | -The code is split into three small modules, following the structure of the Apify Python Actor templates: |
53 | | - |
54 | | -- `my_actor/main.py` - The Actor's main coroutine. It handles the [Actor](https://docs.apify.com/platform/actors) lifecycle, reads the input, sets up [Apify Proxy](https://docs.apify.com/platform/proxy), runs the agent, and stores the result. |
55 | | -- `my_actor/agent.py` - The Browser Use-specific logic. It defines the output schema and a single `run_agent_task` function that builds the LLM, browser, and agent, then returns the agent's structured output. |
56 | | -- `my_actor/__main__.py` - The entry point that runs the `main` coroutine with `asyncio`. |
57 | | - |
58 | | -<Tabs> |
59 | | - <TabItem value="main.py" label="my_actor/main.py"> |
60 | | - <CodeBlock className="language-python"> |
61 | | - {BrowserUseMain} |
62 | | - </CodeBlock> |
63 | | - </TabItem> |
64 | | - <TabItem value="agent.py" label="my_actor/agent.py"> |
65 | | - <CodeBlock className="language-python"> |
66 | | - {BrowserUseAgent} |
67 | | - </CodeBlock> |
68 | | - </TabItem> |
69 | | - <TabItem value="__main__.py" label="my_actor/__main__.py"> |
70 | | - <CodeBlock className="language-python"> |
71 | | - {BrowserUseEntrypoint} |
72 | | - </CodeBlock> |
73 | | - </TabItem> |
74 | | -</Tabs> |
| 47 | +The whole Actor fits in a single file. A `run_agent_task` helper holds the Browser Use-specific logic - it defines the output schema and builds the LLM, browser, and agent - while the `main` coroutine handles the [Actor](https://docs.apify.com/platform/actors) lifecycle, reads the input, sets up [Apify Proxy](https://docs.apify.com/platform/proxy), runs the agent, and stores the result: |
| 48 | + |
| 49 | +<RunnableCodeBlock className="language-python" language="python"> |
| 50 | + {BrowserUseExample} |
| 51 | +</RunnableCodeBlock> |
75 | 52 |
|
76 | 53 | A few things worth pointing out: |
77 | 54 |
|
78 | | -- Keeping the agent setup in `run_agent_task` separates the Browser Use-specific code from the Actor's orchestration logic. `my_actor/main.py` only decides what to read from the input and what to store. |
79 | | -- Passing `output_model_schema=Posts` makes the agent return a validated `Posts` instance via `history.structured_output`, so `my_actor/main.py` can push each item straight to the dataset. Adapt the task and the `Post`/`Posts` models together to fit your own use case. |
| 55 | +- Keeping the agent setup in `run_agent_task` separates the Browser Use-specific code from the Actor's orchestration logic. `main` only decides what to read from the input and what to store. |
| 56 | +- Passing `output_model_schema=Posts` makes the agent return a validated `Posts` instance via `history.structured_output`, so `main` can push each item straight to the dataset. Adapt the task and the `Post`/`Posts` models together to fit your own use case. |
80 | 57 | - `enable_signal_handler=False` leaves signal handling to the Actor, which manages the run's lifecycle. Without it, Browser Use would install its own handlers and interfere with a clean shutdown. |
81 | 58 | - `headless=Actor.configuration.headless` runs the browser without a visible window, which is what you want on the platform. |
82 | 59 |
|
83 | 60 | ## Using Apify Proxy |
84 | 61 |
|
85 | | -Running on the Apify platform gives your agent access to [Apify Proxy](https://docs.apify.com/platform/proxy), which rotates IP addresses to avoid rate limiting and blocking. In the example above, `my_actor/main.py` creates a proxy configuration with `Actor.create_proxy_configuration` and passes a fresh proxy URL to `run_agent_task`. |
| 62 | +Running on the Apify platform gives your agent access to [Apify Proxy](https://docs.apify.com/platform/proxy), which rotates IP addresses to avoid rate limiting and blocking. In the example above, `main` creates a proxy configuration with `Actor.create_proxy_configuration` and passes a fresh proxy URL to `run_agent_task`. |
86 | 63 |
|
87 | | -Browser Use expects the proxy as a `ProxySettings` object with separate `server`, `username`, and `password` fields, whereas `ProxyConfiguration.new_url` returns a single URL string (for example `http://user:pass@proxy.apify.com:8000`). The `_proxy_settings` helper in `my_actor/agent.py` splits that URL into the fields Browser Use expects. To select specific proxy groups or a country, pass the relevant arguments to `Actor.create_proxy_configuration`. For more details, see the [Proxy management](../concepts/proxy-management) guide. |
| 64 | +Browser Use expects the proxy as a `ProxySettings` object with separate `server`, `username`, and `password` fields, whereas `ProxyConfiguration.new_url` returns a single URL string (for example `http://user:pass@proxy.apify.com:8000`). The `_proxy_settings` helper splits that URL into the fields Browser Use expects. To select specific proxy groups or a country, pass the relevant arguments to `Actor.create_proxy_configuration`. For more details, see the [Proxy management](../concepts/proxy-management) guide. |
88 | 65 |
|
89 | 66 | ## Running on the Apify platform |
90 | 67 |
|
91 | 68 | Browser Use drives a real Chromium over CDP, so the Actor needs a browser binary available at runtime. The simplest way to provide one is to build on top of the [Apify Playwright base image](https://hub.docker.com/r/apify/actor-python-playwright), which already ships a browser together with all of its system-level dependencies. Browser Use discovers that browser automatically, so no extra install step is needed in the image. |
92 | 69 |
|
93 | | -<Tabs> |
94 | | - <TabItem value="Dockerfile" label="Dockerfile"> |
95 | | - <CodeBlock className="language-docker"> |
96 | | - {BrowserUseDockerfile} |
97 | | - </CodeBlock> |
98 | | - </TabItem> |
99 | | -</Tabs> |
| 70 | +Disable Browser Use's telemetry and cloud sync inside the Actor by setting the `ANONYMIZED_TELEMETRY=false` and `BROWSER_USE_CLOUD_SYNC=false` environment variables in your Dockerfile. |
100 | 71 |
|
101 | 72 | When running the Actor locally, install the browser once with the `browser-use install` command, which downloads a Chromium build together with its dependencies: |
102 | 73 |
|
|
0 commit comments