browser-use is a Python library that lets a language model operate a web browser the way a person does: read the page, decide, click, type, scroll, and keep going until the task is done. It drives Chromium through Playwright, turns the page into a compact representation the model can reason about, and handles the loop of observing, acting and checking. Booking, scraping behind logins, filling in forms and comparing prices across sites are the everyday uses.
It became the default open library for browser agents within a year of release, and the code base shows it: a small core with many model integrations, examples for most tasks people ask about, and an active community. The company behind it sells a hosted browser and cloud runs; the library, MIT-licensed, runs entirely on your machine with your own model key.
- Repository: github.com/browser-use/browser-use
- Licence: MIT (MIT License)
- Language: Python. Stars: 114.8K. Forks: 12.6K. Last push: Sep 15, 2026.
- Scan: clean, read the notes, Sep 15, 2026, commit d8110c5
Who it is for
Developers automating tasks that only exist behind a website, researchers who need data from pages without an API, and anyone building an assistant that has to act on the web rather than talk about it.
Getting started
1. Install the library (Python 3.11 or newer; in a uv project, uv add browser-use)
pip install browser-use2. Put a model key in .env (a Browser Use key is optional, for their BU2 model or cloud browser)
echo 'OPENAI_API_KEY=sk-...' >> .env3. Save this as agent.py and run it
import asyncio
from browser_use import Agent, ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
async def main():
agent = Agent(task='Find the number of stars of the browser-use repo', llm=ChatOpenAI(model='gpt-5.6-luna'))
history = await agent.run()
print(history.final_result())
asyncio.run(main())Safety scan
We cloned browser-use/browser-use at commit d8110c5 on Sep 15, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No secrets, no self-decoding code, no committed binaries.
- Three pattern hits: bin/setup.sh installs uv from astral.sh for contributors, a constant in the beta module holds the install command for the company's separate terminal product, and one 19,000-character line in demo_mode.py is an inline SVG logo.
- The bare-IP URLs are test cases: 8.8.8.8, 1.1.1.1, TEST-NET addresses and a 999.999.999.999 that exists to fail.
- No lockfile is committed (uv.lock is gitignored), so pip or uv resolves current versions of playwright and the rest at install time. There is nothing for OSV to check, and nothing pinning you to an old version either.
- Nine workflows, none using pull_request_target; 1 of 19 third-party actions pinned to a commit. Security policy, licence and contributing guide present.
- The library can drive a browser you are logged in to. Give it its own profile and its own accounts.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | 3 pattern hits found and read; every one is listed under the raw findings. |
| Install-time code | 1 installer script (one fetches and runs a remote script) |
| Committed binaries | None. |
| CI workflows | 9 workflows. None use pull_request_target. 18 of 19 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 40 distinct hosts referenced from source; most often github.com, cloud.browser-use.com, www.google.com, test.com. 20 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | No lockfile to check: dependencies are declared as ranges, so what gets installed is whatever is current on the day. |
| Project hygiene | Has security policy, licence file, contributing guide. Missing automated dependency updates, CodeQL. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
Pattern hits (3)
| Where | Rule | Match |
|---|---|---|
| bin/setup.sh:31 | download-piped-to-shell | curl -LsSf https://astral.sh/uv/install.sh | sh |
| browser_use/beta/service.py:91 | download-piped-to-shell | TERMINAL_INSTALL_COMMAND = 'curl -fsSL https://browser-use.com/terminal/install.sh | sh' |
| browser_use/browser/demo_mode.py:485 | very-long-line | 19359 chars |
URLs to bare IP addresses (20)
| Where | Rule | Match |
|---|---|---|
| tests/ci/security/test_ip_blocking.py:25 | ip-literal-url | assert watchdog._is_url_allowed('http://180.1.1.1/supersafe.txt') is False |
| tests/ci/security/test_ip_blocking.py:26 | ip-literal-url | assert watchdog._is_url_allowed('https://8.8.8.8/') is False |
| tests/ci/security/test_ip_blocking.py:27 | ip-literal-url | assert watchdog._is_url_allowed('http://1.1.1.1:8080/api') is False |
| tests/ci/security/test_ip_blocking.py:28 | ip-literal-url | assert watchdog._is_url_allowed('https://142.250.185.46/search') is False |
| tests/ci/security/test_ip_blocking.py:29 | ip-literal-url | assert watchdog._is_url_allowed('http://93.184.216.34/') is False |
| tests/ci/security/test_ip_blocking.py:67 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8:80/') is False |
| tests/ci/security/test_ip_blocking.py:68 | ip-literal-url | assert watchdog._is_url_allowed('https://8.8.8.8:443/') is False |
| tests/ci/security/test_ip_blocking.py:73 | ip-literal-url | assert watchdog._is_url_allowed('http://1.2.3.4/path/to/resource') is False |
| tests/ci/security/test_ip_blocking.py:74 | ip-literal-url | assert watchdog._is_url_allowed('http://5.6.7.8/api?key=value') is False |
| tests/ci/security/test_ip_blocking.py:75 | ip-literal-url | assert watchdog._is_url_allowed('https://9.10.11.12/path/to/file.html#anchor') is False |
| tests/ci/security/test_ip_blocking.py:85 | ip-literal-url | assert watchdog._is_url_allowed('http://180.1.1.1/supersafe.txt') is True |
| tests/ci/security/test_ip_blocking.py:88 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is True |
| tests/ci/security/test_ip_blocking.py:224 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is False |
| tests/ci/security/test_ip_blocking.py:242 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is False |
| tests/ci/security/test_ip_blocking.py:263 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is False |
| tests/ci/security/test_ip_blocking.py:316 | ip-literal-url | assert watchdog._is_url_allowed('http://999.999.999.999/') is True |
| tests/ci/security/test_ip_blocking.py:413 | ip-literal-url | assert watchdog._is_url_allowed('http://180.1.1.1/supersafe.txt') is True |
| tests/ci/security/test_ip_blocking.py:417 | ip-literal-url | assert watchdog._is_url_allowed('https://8.8.8.8/') is True |
| tests/ci/security/test_ip_blocking.py:442 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is False |
| tests/ci/security/test_ip_blocking.py:471 | ip-literal-url | assert watchdog._is_url_allowed('http://8.8.8.8/') is False |
Installer scripts (1)
- bin/setup.sh, 53 lines, fetches and runs a remote script; talks to astral.sh, github.com, redsymbol.net, www.gnu.org
By the numbers
| Stars | 114.8K |
|---|---|
| Forks | 12.6K |
| Contributors | 381 |
| Commits | 10.3K |
| Open issues | 133 |
| Open pull requests | 297 |
| Releases | 137 |
| Latest release | 0.13.10 |
| Licence | MIT |
| Main language | Python |
| Project age | 1 year |
| Last push | Sep 15, 2026 |
| Tracked files | 518 |
| Lines of code | 142.8K |
| Checkout size | 9 MB |
Lines by language: Python 110.9K, JSON 17.1K, Markdown 12.3K, YAML 1,559, Shell 374, HTML 271.
Questions
Is browser-use free?
The library is MIT-licensed and free. You pay for the model you connect, and browser agents are token-hungry because every step sends the page state to the model. The hosted Browser Use Cloud is optional and paid.
Can browser-use log in to sites for me?
Yes, and that is where care is needed. It can use a browser profile you are already logged in to, or fill in credentials you give it. Treat the agent as someone you have handed your session to: use a separate browser profile, scope the accounts it can reach, and keep an eye on what it does.
Which models work best with browser-use?
Models with strong tool use and vision do best. The maintainers' benchmarks favour the current frontier models from OpenAI, Anthropic and Google; smaller and local models work for simple tasks but lose the thread on long ones. The model is a constructor argument, so switching is one line.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.