Make websites accessible for AI agents — in TypeScript
A TypeScript-first library for building AI-powered web agents that can autonomously browse, interact with, and extract data from the web using LLMs and Playwright.
Production-capable TypeScript port, inspired by and behavior-aligned with Python browser-use — with a native Node.js experience, full type safety, and first-class support for all major LLM providers.
- 🤖 Autonomous Browser Control — AI-driven navigation, clicking, typing, form filling, scrolling, and tab management
- 🧠 15+ LLM Providers & Adapters — OpenAI, Anthropic, Google Gemini, Azure, AWS Bedrock, Groq, Ollama, DeepSeek, OpenRouter, Mistral, Cerebras, Browser Use, LiteLLM, OCI Raw, Vercel, and custom providers
- 👁️ Vision Support — Screenshot-based understanding for visual web interactions
- 🔧 45+ Built-in Actions — Navigation, element interaction, scrolling, forms, tabs, content extraction, file I/O, and more
- 🧩 Custom Actions — Extensible registry with Zod schema validation, domain restrictions, and page filters
- 🔌 MCP Server — Model Context Protocol support for Claude Desktop and MCP-compatible clients
- ⌨️ CLI Tool — Interactive and one-shot modes for quick browser tasks
- 🔒 Security First — Sensitive data masking, domain restrictions, and Chromium sandboxing
- 📊 Observability — Event system, telemetry, performance tracing, and session recording (GIF)
- 🐳 Docker Ready — Configurable for containerized and CI/CD environments
npm install browser-use
# Playwright browsers are installed automatically via postinstallexport OPENAI_API_KEY=sk-your-api-key
# or ANTHROPIC_API_KEY, GOOGLE_API_KEY, etc.import{Agent}from'browser-use';import{ChatOpenAI}from'browser-use/llm/openai';constagent=newAgent({task: 'Go to google.com and search for "TypeScript tutorials"',llm: newChatOpenAI({model: 'gpt-4o',apiKey: process.env.OPENAI_API_KEY,}),});consthistory=awaitagent.run();console.log('Result:',history.final_result());console.log('Success:',history.is_successful());npx tsx example.ts# Interactive mode
npx browser-use
# One-shot task
npx browser-use "Go to example.com and extract the page title"# With specific model
npx browser-use --model claude-sonnet-4-20250514 -p "Search for AI news"# Headless mode
npx browser-use --headless -p "Check the weather"# MCP server mode
npx browser-use --mcp
# Minimal direct-browser MCP server for coding agents
npx browser-use --cli-mcp
# Install the bundled coding-agent skill (codex, claude, cursor, etc.)
npx browser-use skill install --target codexThe bundled browser-use skill teaches coding
agents to drive the persistent browser through the two-tool CLI MCP server or
the browser-use-direct fallback. Run npx browser-use skill install without
a target to install it for every supported coding agent, or use
npx browser-use skill show to inspect it first.
┌─────────────────────────────────────────────────────┐
│ Browser-Use │
├─────────────────────────────────────────────────────┤
│ Agent ← MessageManager ← LLM Providers │
│ ↓ │
│ Controller → Action Registry → BrowserSession │
│ ↓ │
│ DomService │
└─────────────────────────────────────────────────────┘
| Component | Description |
|---|---|
| Agent | Central orchestrator — runs the observe → think → act loop |
| Controller | Manages action registration and execution via Registry |
| BrowserSession | Playwright wrapper — browser lifecycle, tab management, screenshots |
| DomService | Extracts interactive elements with indexed mapping for LLM consumption |
| MessageManager | Manages LLM conversation history with token optimization |
| LLM Providers | Unified BaseChatModel interface across 15+ providers and adapters |
- Agent receives a natural language task
- DomService extracts the current page state (interactive elements + optional screenshot)
- LLM analyzes the state and returns actions to take
- Controller validates and executes actions through the Registry
- Results feed back to the LLM for the next step
- Loop continues until
doneaction ormax_steps
| Provider | Import | Vision | Notes |
|---|---|---|---|
| OpenAI | browser-use/llm/openai | ✅ | Default provider, reasoning models (o1/o3/o4) |
| Codex | browser-use/llm/codex | ✅ | Experimental ChatGPT/Codex OAuth provider |
| Anthropic | browser-use/llm/anthropic | ✅ | Prompt caching support |
| Google Gemini | browser-use/llm/google | ✅ | Extended thinking support |
| Azure OpenAI | browser-use/llm/azure | ✅ | Enterprise deployment |
| AWS Bedrock | browser-use/llm/aws | ✅ | Claude via AWS |
| Groq | browser-use/llm/groq | ❌ | Fastest inference |
| Ollama | browser-use/llm/ollama | ❌ | Local/self-hosted models |
| DeepSeek | browser-use/llm/deepseek | ❌ | Cost-effective |
| OpenRouter | browser-use/llm/openrouter | Varies | Multi-model routing |
| Mistral | browser-use/llm/mistral | Varies | Mistral models |
| Cerebras | browser-use/llm/cerebras | ❌ | Fast inference |
| Browser Use | browser-use/llm/browser-use | Varies | Hosted Browser Use LLM |
| LiteLLM | browser-use/llm/litellm | Varies | OpenAI-compatible LiteLLM gateway |
| OCI Raw | browser-use/llm/oci-raw | Varies | Oracle Cloud Generative AI |
| Vercel | browser-use/llm/vercel | Varies | Vercel AI Gateway / routed models |
Provider examples
// OpenAIimport{ChatOpenAI}from'browser-use/llm/openai';constllm=newChatOpenAI({model: 'gpt-4o',apiKey: process.env.OPENAI_API_KEY,});// Anthropicimport{ChatAnthropic}from'browser-use/llm/anthropic';constllm=newChatAnthropic({model: 'claude-sonnet-4-20250514',apiKey: process.env.ANTHROPIC_API_KEY,});// Google Geminiimport{ChatGoogle}from'browser-use/llm/google';constllm=newChatGoogle('gemini-2.5-flash');// Ollama (local)import{ChatOllama}from'browser-use/llm/ollama';constllm=newChatOllama('llama3','http://localhost:11434');// OpenAI Reasoning Modelsconstllm=newChatOpenAI({model: 'o3-mini',reasoningEffort: 'medium'});// Codex OAuth provider (experimental)// First run: npx browser-use auth codex loginimport{ChatCodex}from'browser-use/llm/codex';constcodexLlm=newChatCodex({model: 'gpt-5.5'});// Browser Use gateway: one BROWSER_USE_API_KEY can route provider/model idsimport{ChatBrowserUse}from'browser-use/llm/browser-use';constgatewayLlm=newChatBrowserUse({model: 'anthropic/claude-sonnet-4-6',});constagent=newAgent({task: `Go to amazon.com, search for "wireless keyboard", extract the name, price, and rating of the first 5 products as JSON`,
llm,use_vision: true,});consthistory=awaitagent.run(30);console.log(history.final_result());constagent=newAgent({task: 'Login to the dashboard',
llm,sensitive_data: {'*.example.com': {username: process.env.SITE_USERNAME!,password: process.env.SITE_PASSWORD!,},},browser_session: newBrowserSession({browser_profile: newBrowserProfile({allowed_domains: ['*.example.com'],}),}),});importfsfrom'node:fs';import{Controller,ActionResult}from'browser-use';import{z}from'zod';constcontroller=newController();controller.registry.action('Save screenshot to file',{param_model: z.object({filename: z.string().describe('Output filename'),}),})(asyncfunctionsave_screenshot(params,ctx){constscreenshot=awaitctx.page.screenshot();fs.writeFileSync(`./screenshots/${params.filename}`,screenshot);returnnewActionResult({extracted_content: `Screenshot saved as ${params.filename}`,});});constagent=newAgent({task: '...', llm, controller });constagent=newAgent({task: 'Navigate to hacker news and summarize the top stories',
llm,use_vision: true,vision_detail_level: 'high',// 'auto' | 'low' | 'high'generate_gif: './session.gif',});constagent=newAgent({task: `Compare "Sony WH-1000XM5" prices: 1. Open amazon.com and search for the product 2. Open bestbuy.com in a new tab and search 3. Provide a comparison summary`,
llm,use_vision: true,});constagent=newAgent({task: '...', llm });agent.eventbus.on('CreateAgentStepEvent',(event)=>{console.log('Step completed:',event.step_id);});awaitagent.run();constagent=newAgent({task: 'Your task',
llm,use_vision: true,// Enable screenshot analysismax_actions_per_step: 5,// Actions per LLM callmax_failures: 3,// Max retries on failuregenerate_gif: './recording.gif',// Session recordingvalidate_output: true,// Strict output validationuse_thinking: true,// Extended thinking promptsllm_timeout: 60,// LLM call timeout (seconds)step_timeout: 180,// Step timeout (seconds)extend_system_message: 'Be concise',// Custom prompt additions});consthistory=awaitagent.run(50);// Max 50 stepsimport{BrowserProfile,BrowserSession}from'browser-use';constprofile=newBrowserProfile({headless: true,viewport: {width: 1920,height: 1080},user_data_dir: './my-profile',// Persistent sessionsallowed_domains: ['*.example.com'],// Domain restrictionshighlight_elements: true,// Visual debuggingproxy: {server: 'http://proxy:8080'},});constsession=newBrowserSession({browser_profile: profile});constagent=newAgent({task: '...', llm,browser_session: session});| Variable | Description |
|---|---|
OPENAI_API_KEY | OpenAI API key |
ANTHROPIC_API_KEY | Anthropic API key |
GOOGLE_API_KEY | Google API key |
BROWSER_USE_HEADLESS | Run browser headlessly (true/false) |
BROWSER_USE_LOGGING_LEVEL | Log level: debug, info, warning, error |
BROWSER_USE_ALLOWED_DOMAINS | Comma-separated domain allowlist |
ANONYMIZED_TELEMETRY | Enable/disable anonymous telemetry |
See Configuration Guide for the full list.
Browser-Use can run as an MCP server, exposing browser automation as tools for Claude Desktop:
npx browser-use --mcpAdd to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"browser-use": {
"command": "npx",
"args": ["browser-use", "--mcp"],
"env": {
"OPENAI_API_KEY": "your-api-key"
}
}
}
}Core MCP tools include retry_with_browser_use_agent, browser_navigate, browser_click, browser_type, browser_get_state, browser_extract_content, browser_scroll, browser_go_back, browser_list_tabs, browser_switch_tab, browser_close_tab, browser_list_sessions, browser_close_session, and browser_close_all. The server also exposes registered controller actions as additional MCP tools.
See MCP Server Guide for more details.
- Sensitive Data Masking — Credentials are automatically masked in logs and LLM context
- Domain Restrictions — Lock browser navigation to trusted domains
- Domain-scoped Secrets — Credentials are only injected on matching domains
- Sensitive Data Warning — Browser-Use warns when
sensitive_datais used withoutallowed_domains - Chromium Sandbox — Enabled by default for production security
constagent=newAgent({task: 'Login and fetch invoices',
llm,sensitive_data: {'*.example.com': {username: process.env.USERNAME!,password: process.env.PASSWORD!,},},browser_session: newBrowserSession({browser_profile: newBrowserProfile({allowed_domains: ['*.example.com'],}),}),});See Security Guide for production deployment best practices.
| Document | Description |
|---|---|
| Quick Start | Get started in 5 minutes |
| Architecture | System design and component overview |
| API Reference | Complete API documentation |
| Configuration | All configuration options |
| LLM Providers | Provider setup and comparison |
| Actions | Built-in and custom actions |
| MCP Server | MCP integration guide |
| Security | Security best practices |
| Examples | More code examples |
| Contributing | Contribution guidelines |
# Install dependencies
pnpm install
# Build
pnpm build
# Run tests
pnpm test# Lint & format
pnpm lint
pnpm prettier
# Type checking
pnpm typecheck
# Run an example
pnpm exec tsx examples/simple-search.ts- Node.js >= 18.0.0
- LLM API Key — At least one supported provider
- Playwright — Installed automatically as a dependency