# Headless Browser Usage
Browsing runs **headless by default** — no visible browser window, minimal resource usage. This guide covers configuration and usage patterns.
## Default Behavior
```rust
use browsing::BrowserProfile;
// Headless by default — this is all you need
let profile = BrowserProfile::default();
```
This automatically enables:
- `--headless=new` (modern Chrome headless mode)
- `--disable-gpu`
- `--disable-extensions`
- `--disable-sync`
- `--no-first-run`
- `--mute-audio`
- Plus 12 more lightweight flags for fast, minimal operation
## Quick Start
### Basic Setup
```rust
use browser_use::agent::service::Agent;
use browser_use::browser::{Browser, BrowserProfile};
use browser_use::agent::views::AgentSettings;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Default profile is headless — no configuration needed
let profile = BrowserProfile::default();
let browser = Browser::new(profile);
// Configure your LLM (example with mock or real implementation)
let llm = create_llm_client().await?;
// Create agent with task
let task = "Navigate to https://example.com and extract the main heading text";
let agent = Agent::new(task, browser, llm)
.with_max_steps(10)
.with_settings(AgentSettings {
use_vision: browser_use::agent::views::VisionMode::Auto,
max_failures: 3,
use_thinking: true,
..Default::default()
});
// Run agent to completion
let history = agent.run().await?;
println!("Agent completed successfully!");
println!("Total steps: {}", history.number_of_steps());
println!("Duration: {:.2}s", history.total_duration_seconds());
// Browser automatically cleans up when dropped
// Or explicitly: browser.stop().await?;
Ok(())
}
```
## Advanced Configuration
### Using Existing Browser Instance
```rust
// Connect to an already running browser via CDP
let mut browser = Browser::new(BrowserProfile::default())
.with_cdp_url("ws://localhost:9222".to_string());
browser.start().await?;
browser.navigate("https://example.com").await?;
```
### Custom Browser Executable
```rust
use std::path::PathBuf;
// Headless by default
let profile = BrowserProfile::default();
let mut browser = Browser::new(profile);
// browser.with_executable_path(PathBuf::from("/usr/bin/google-chrome-stable"));
browser.start().await?;
```
### Visible Browser (for debugging)
```rust
// Show the browser window for debugging
let profile = BrowserProfile::default().with_headless(false);
let browser = Browser::new(profile);
```
### Domain Restrictions
```rust
let profile = BrowserProfile {
allowed_domains: Some(vec![
"example.com".to_string(),
"subdomain.example.com".to_string(),
]),
..Default::default() // headless = true by default
};
let browser = Browser::new(profile);
// Browser will only allow navigation to specified domains
```
## Error Handling
The browser use cases should include proper error handling:
```rust
use browser_use::error::BrowserUseError;
match agent.run().await {
Ok(history) => {
println!("Success: {} steps", history.number_of_steps());
}
Err(BrowserUseError::Browser(msg)) => {
eprintln!("Browser error: {}", msg);
// Try to fallback or retry
}
Err(BrowserUseError::Llm(msg)) => {
eprintln!("LLM error: {}", msg);
// Check API keys, model availability
}
Err(e) => {
eprintln!("Other error: {:?}", e);
}
}
```
## Headless Browser Requirements
For headless mode to work, you need:
1. **Chrome/Chromium** installed and accessible in PATH
2. **Chrome DevTools Protocol** (CDP) support (included with Chrome)
3. **Permissions** to launch processes
4. **Sufficient system resources** (RAM for browser instances)
### Installing Chrome
#### Ubuntu/Debian
```bash
sudo apt update
sudo apt install -y google-chrome-stable
# or
sudo apt install -y chromium-browser
```
#### macOS
```bash
# Using Homebrew
brew install --cask google-chrome
# Or download from https://www.google.com/chrome/
```
#### Windows
Download from https://www.google.com/chrome/ and install to default location
### Verifying Installation
```bash
# Check if Chrome is in PATH
google-chrome --version
# or
chromium-browser --version
```
## CI/CD Considerations
### GitHub Actions Example
```yaml
name: Browser Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y google-chrome-stable
- name: Run tests
run: cargo test --test integration_workflow_test
env:
DISPLAY: ':99'
```
### Docker Example
```dockerfile
FROM rust:1.70
# Install Chrome
apt-get update && \
apt-get install -y google-chrome-stable
WORKDIR /app
COPY . .
RUN cargo build --release
CMD ["cargo", "run", "--release"]
```
## Troubleshooting
### "No browser executable found"
**Problem**: Browser cannot find Chrome/Chromium executable.
**Solutions**:
1. Install Chrome/Chromium
2. Add Chrome to system PATH
3. Use `with_executable_path()` to specify location:
```rust
browser.with_executable_path(PathBuf::from("/path/to/chrome"));
```
### CDP Connection Issues
**Problem**: Browser starts but CDP connection fails.
**Solutions**:
1. Ensure Chrome wasn't launched with `--disable-dev-shm-usage`
2. Check if another instance is using the same debug port
3. Try different user data directory: `user_data_dir: Some("/tmp/chrome_test".into())`
### Headless Mode Issues
**Problem**: Headless mode doesn't work on some systems.
**Solutions**:
1. On Linux, ensure Xvfb (virtual display) is running:
```bash
Xvfb :99 -screen 0 1024x768x24 &
export DISPLAY=:99
```
2. On macOS, try disabling sandbox flags:
```rust
let launcher = BrowserLauncher::new(profile);
```
### Memory Issues
**Problem**: Browser consumes too much memory.
**Solutions**:
1. Use lighter weight Chromium builds
2. Limit number of concurrent browser instances
3. Explicitly close browsers when done: `browser.stop().await?`
## Security Considerations
### File Uploads
File upload paths are automatically validated for security:
```rust
// These are REJECTED by default
"../../../etc/passwd" // Path traversal
"~/.ssh/id_rsa" // Home directory access
"/etc/shadow" // System files
// This is ACCEPTED
"/tmp/safe_file.txt" // Temporary directory
"./local_file.txt" // Relative path
```
### JavaScript Execution
JavaScript code is automatically sanitized:
```rust
// These are BLOCKED
"document.cookie = 'hacked'"
"localStorage.setItem('token', 'stolen')"
"eval('malicious code')"
// These are ALLOWED
"document.title = 'Test'"
"console.log('debug message')"
"return document.body.innerHTML"
```
## Next Steps
1. **Start Simple**: Use the basic setup example above
2. **Configure LLM**: Replace mock LLM with your actual LLM implementation
3. **Customize Browser**: Adjust browser profile settings for your use case
4. **Add Error Handling**: Implement robust error handling for production
5. **Test Thoroughly**: Use the provided tests as examples for your own tests
For more examples, see the `tests/` directory in the repository.