browsing 0.1.6

Browser automation: navigate, click, extract, screenshot. Standalone browser control via CDP.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
# Browsing

**Lightweight, headless-first MCP/API for browser automation**

A concise MCP server and Rust library: **navigate**, **get_links**, **follow_link**, **list_content** (links+images), **get_content**, **get_image**, **save_content**, **screenshot** (full or element). Lazy browser init. Parallel reads via RwLock. Runs headless by default with 17+ lightweight Chrome flags for fast, minimal operation. No LLM or AI dependencies.

## ๐ŸŽฏ Usage Modes

1. **๐Ÿ”Œ MCP Server** (primary) - `navigate`, `get_links`, `follow_link`, `list_content`, `get_content`, `get_image`, `save_content`, `screenshot`, `generate_sitemap` tools
2. **โŒจ๏ธ CLI** - Browser automation tasks
3. **๐Ÿ“ฆ Library** - Browser automation via CDP

## โœจ Why Browsing?

Browser automation is challenging. You need to:

- **Extract structured data from unstructured HTML** - Parse complex DOM trees into usable representations
- **Handle browser automation reliably** - Manage browser lifecycle, CDP connections, and process management
- **Maintain testability** - Mock components for unit testing without real browsers
- **Support extensibility** - Add custom actions and browser backends

**Browsing solves all of this** with a clean, modular, and well-tested architecture.

## ๐Ÿง  Why Better Than Chrome DevTools?

Chrome DevTools Protocol (CDP) is an **engine** โ€” it gives you raw browser control, but you must build all intelligence yourself. Most "headless browsing" tools are just CDP wrappers with slightly nicer APIs.

Browsing is a **self-driving car** on top of that engine. It adds five intelligence layers that are hard to replicate by simply wrapping CDP:

| Layer | CDP (Raw Protocol) | Browsing (Browser Automation) |
|---|---|---|
| **Perception** | Raw DOM tree | Semantic understanding: page intent, form schemas, action affordances |
| **Action** | Brittle `backend_node_id`/XPath | Self-healing element resolution: index โ†’ text โ†’ semantic fallback |
| **Memory** | Nothing persists | Session history, site-specific strategies |
| **Observability** | Protocol logs | DOM state snapshots and action traces |

**The goal**: CDP becomes invisible. Users think about tasks, not WebSocket messages or element IDs.

## ๐ŸŽฏ Key Features

### ๐Ÿ—๏ธ Trait-Based Architecture
- **BrowserClient trait** - Abstract browser operations for easy mocking and alternative backends
- **DOMProcessor trait** - Pluggable DOM processing implementations
- **ActionHandler trait** - Extensible action system for custom behaviors

### ๐ŸŒ Full Browser Automation
- **Headless by default** โ€” `BrowserProfile::default()` runs headless with `--headless=new`
- **17+ lightweight flags** โ€” disables extensions, sync, background networking, logging, and more
- Cross-platform support (macOS, Linux, Windows)
- Automatic browser detection
- Chrome DevTools Protocol (CDP) integration
- Tab management (create, switch, close)
- Screenshot capture (page and element-level)

### ๐Ÿ“Š Advanced DOM Processing
- Full CDP integration (DOM, AX tree, Snapshot)
- Text serialization with interactive element indices
- Accessibility tree support for better semantic understanding

### ๐Ÿ”ง Extensible & Maintainable
- Manager-based architecture (TabManager, NavigationManager, ScreenshotManager)
- Custom action registration
- Utility traits for reduced code duplication
- Comprehensive test coverage (350+ tests)

## ๐Ÿ“ฆ Installation

### As a Library

```toml
[dependencies]
browsing = "0.1"
tokio = { version = "1.40", features = ["full"] }
```

### As a CLI Tool

```bash
cargo install --path . --bin browsing
```

### As an MCP Server

```bash
cargo build --release --bin browsing-mcp
```

## ๐Ÿš€ ๏ฟฝ Quick Start## ๏ฟฝ Quick Start

### 1๏ธโƒฃ CLI Usage

```bash
# Run a browser automation task (headless by default)
browsing run "Navigate to example.com and extract content" --url https://news.ycombinator.com

# Run with visible browser
browsing run "Navigate to example.com and extract content" --url https://news.ycombinator.com --no-headless

# Launch a headless browser and get CDP URL (headless by default)
browsing launch

# Launch with visible browser
browsing launch --no-headless

# Connect to existing browser
browsing connect ws://localhost:9222/devtools/browser/abc123
```

**๐Ÿ“– [Full CLI Documentation](docs/CLI_USAGE.md)**

### 2๏ธโƒฃ MCP Server Usage

Configure in Claude Desktop (`~/Library/Application Support/Claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "browsing": {
      "command": "/path/to/browsing/target/release/browsing-mcp",
      "env": {
        "BROWSER_USE_HEADLESS": "true"
      }
    }
  }
}
```

Then ask Claude:
```
"Navigate to rust-lang.org, get the links, follow the second link, and screenshot the main content area"
```

**๐Ÿ“– [Full MCP Documentation](docs/MCP_USAGE.md)**

### 3๏ธโƒฃ Library Usage

```rust
use anyhow::Result;
use browsing::Browser;
use browsing::browser::BrowserProfile;

#[tokio::main]
async fn main() -> Result<()> {
    browsing::init();

    let mut browser = Browser::new(BrowserProfile::default());
    browser.start().await?;

    browser.navigate("https://example.com").await?;

    let title = browser.get_current_page_title().await?;
    println!("Title: {}", title);

    let _ = browser.stop().await;
    Ok(())
}
```

**๐Ÿ“– [Full Library Documentation](docs/LIBRARY_USAGE.md)**

### Browser Launch Options

```rust
use browsing::{Browser, BrowserProfile};

// Option 1: Auto-launch headless browser (default)
let profile = BrowserProfile::default(); // headless = true by default
let browser = Browser::new(profile);

// Option 2: Launch with visible browser
let profile = BrowserProfile::default().with_headless(false);
let browser = Browser::new(profile);

// Option 3: Connect to existing browser
let browser = Browser::new(BrowserProfile::default())
    .with_cdp_url("http://localhost:9222".to_string());

// Option 4: Custom browser executable
use browsing::browser::launcher::BrowserLauncher;
let launcher = BrowserLauncher::new(profile)
    .with_executable_path(std::path::PathBuf::from("/path/to/chrome"));
```

### Using Traits for Testing

#### Standalone Browser Testing (no AI required)

```rust
use browsing::traits::{BrowserClient, DOMProcessor};
use std::sync::Arc;

// Test your browser automation logic directly
```


## ๐Ÿ“š Usage Examples

### Content Download

```rust
use browsing::{Browser, BrowserProfile};
use browsing::dom::DOMProcessorImpl;
use browsing::traits::DOMProcessor;

#[tokio::main]
async fn main() -> browsing::error::Result<()> {
    let mut browser = Browser::new(BrowserProfile::default());
    browser.start().await?;

    // Navigate to website
    browser.navigate("https://www.ibm.com").await?;
    tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;

    // Extract content
    let cdp_client = browser.get_cdp_client()?;
    let session_id = browser.get_session_id()?;
    let target_id = browser.get_current_target_id()?;

    let dom_processor = DOMProcessorImpl::new()
        .with_cdp_client(cdp_client, session_id)
        .with_target_id(target_id);

    let state = dom_processor.get_serialized_dom().await?;
    let page_content = state.text_representation(None).unwrap_or_default();
    println!("Extracted {} bytes of content", page_content.len());

    // Save to file
    std::fs::write("ibm_content.txt", page_content)?;
    Ok(())
}
```

**Run this example:**
```bash
cargo run --example ibm_content_download
```

### Screenshot Capture

```rust
use browsing::Browser;

let browser = Browser::new(BrowserProfile::default());
browser.start().await?;

// Full page screenshot
let screenshot_data = browser.take_screenshot(
    Some("screenshot.png"),  // path
    true,                     // full_page
    None,                     // format
    None,                     // quality
).await?;

// Viewport only
let viewport = browser.take_screenshot(
    Some("viewport.png"),
    false,
    None,
    None,
).await?;
```

### Direct Browser Control

```rust
use browsing::{Browser, BrowserProfile};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut browser = Browser::new(BrowserProfile::default());
    browser.start().await?;

    // Navigate
    browser.navigate("https://example.com").await?;

    // Get current URL
    let url = browser.get_current_url().await?;
    println!("Current URL: {}", url);

    // Tab management
    use browsing::traits::BrowserClient;
    browser.create_tab(Some("https://hackernews.com")).await?;
    let tabs = browser.get_tabs().await?;
    println!("Open tabs: {}", tabs.len());

    // Switch tabs
    browser.switch_to_tab(&tabs[0].target_id).await?;

    Ok(())
}
```

### Custom Actions

```rust
use browsing::tools::views::{ActionHandler, ActionParams, ActionContext, ActionResult};
use browsing::error::Result;
use browsing::tools::Tools;

struct CustomActionHandler;

#[async_trait::async_trait]
impl ActionHandler for CustomActionHandler {
    async fn execute(
        &self,
        params: &ActionParams,
        context: &mut ActionContext<'_>,
    ) -> Result<ActionResult> {
        // Custom action logic here
        Ok(ActionResult {
            extracted_content: Some("Custom result".to_string()),
            ..Default::default()
        })
    }
}

// Register custom action
let mut tools = Tools::default();
tools.register_custom_action(
    "custom_action".to_string(),
    "Description of custom action".to_string(),
    None,  // domains
    CustomActionHandler,
);
```

## ๐Ÿ—๏ธ Architecture

Browsing follows **SOLID principles** with a focus on separation of concerns, testability, and maintainability.

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    Browser Automation                       โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚   Browser   โ”‚ DOMProcessor โ”‚        Tools            โ”‚  โ”‚
โ”‚  โ”‚   (trait)   โ”‚    (trait)   โ”‚                         โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚         โ”‚             โ”‚                      โ”‚           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚             โ”‚                      โ”‚
    โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”
    โ”‚  Browser   โ”‚ โ”‚DomSvc  โ”‚        โ”‚   Handlers   โ”‚
    โ”‚            โ”‚ โ”‚        โ”‚        โ”‚              โ”‚
    โ”‚TabManager  โ”‚ โ”‚CDP     โ”‚        โ”‚Navigation    โ”‚
    โ”‚NavManager  โ”‚ โ”‚HTML    โ”‚        โ”‚Interaction   โ”‚
    โ”‚Screenshot  โ”‚ โ”‚Tree    โ”‚        โ”‚Tabs          โ”‚
    โ”‚            โ”‚ โ”‚Builder โ”‚        โ”‚Content       โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

### Key Components

| Component | Responsibility | Trait-Based |
|-----------|---------------|-------------|
| **Browser** | Manages browser session and lifecycle | Implements `BrowserClient` |
| **DOMProcessor** | Extracts and serializes DOM | Implements `DOMProcessor` |
| **Tools** | Action registry and execution | Uses `BrowserClient` trait |
| **Handlers** | Specific action implementations | Use `ActionHandler` trait |

## ๐Ÿ“ Project Structure

```
browsing/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ agent/              # Agent view types (used by tools layer)
โ”‚   โ”‚   โ”œโ”€โ”€ views.rs        # Data types
โ”‚   โ”‚   โ””โ”€โ”€ memory.rs       # Session memory types
โ”‚   โ”œโ”€โ”€ browser/            # Browser management
โ”‚   โ”‚   โ”œโ”€โ”€ session.rs      # Browser session (BrowserClient impl)
โ”‚   โ”‚   โ”œโ”€โ”€ tab_manager.rs  # Tab operations
โ”‚   โ”‚   โ”œโ”€โ”€ navigation.rs   # Navigation operations
โ”‚   โ”‚   โ”œโ”€โ”€ screenshot.rs   # Screenshot operations
โ”‚   โ”‚   โ”œโ”€โ”€ cdp.rs          # CDP WebSocket client
โ”‚   โ”‚   โ”œโ”€โ”€ launcher.rs     # Browser launcher
โ”‚   โ”‚   โ””โ”€โ”€ profile.rs      # Browser configuration
โ”‚   โ”œโ”€โ”€ dom/                # DOM processing
โ”‚   โ”‚   โ”œโ”€โ”€ processor.rs    # DOMProcessor trait impl
โ”‚   โ”‚   โ”œโ”€โ”€ serializer.rs   # Text serialization
โ”‚   โ”‚   โ”œโ”€โ”€ tree_builder.rs # DOM tree construction
โ”‚   โ”‚   โ”œโ”€โ”€ cdp_client.rs   # CDP wrapper for DOM
โ”‚   โ”‚   โ””โ”€โ”€ html_converter.rs # HTML to markdown
โ”‚   โ”œโ”€โ”€ tools/              # Action system
โ”‚   โ”‚   โ”œโ”€โ”€ service.rs      # Tools registry
โ”‚   โ”‚   โ”œโ”€โ”€ handlers/       # Action handlers
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ navigation.rs
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ interaction.rs
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ tabs.rs
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ content.rs
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ advanced.rs
โ”‚   โ”‚   โ””โ”€โ”€ params.rs       # Parameter extraction
โ”‚   โ”œโ”€โ”€ traits/             # Core trait abstractions
โ”‚   โ”‚   โ”œโ”€โ”€ browser_client.rs  # BrowserClient trait
โ”‚   โ”‚   โ””โ”€โ”€ dom_processor.rs   # DOMProcessor trait
โ”‚   โ”œโ”€โ”€ actor/              # Low-level interactions
โ”‚   โ”‚   โ”œโ”€โ”€ page.rs         # Page operations
โ”‚   โ”‚   โ”œโ”€โ”€ element.rs      # Element operations
โ”‚   โ”‚   โ”œโ”€โ”€ mouse.rs        # Mouse interactions
โ”‚   โ”‚   โ””โ”€โ”€ keyboard.rs     # Keyboard input
โ”‚   โ”œโ”€โ”€ config.rs           # Configuration
โ”‚   โ”œโ”€โ”€ error.rs            # Error types
โ”‚   โ”œโ”€โ”€ logging.rs          # Logging setup
โ”‚   โ”œโ”€โ”€ metrics.rs          # Metrics collection
โ”‚   โ”œโ”€โ”€ utils.rs            # Utilities
โ”‚   โ””โ”€โ”€ views.rs            # Shared data types
โ””โ”€โ”€ Cargo.toml
```

## ๐ŸŽจ Design Principles

### Trait-Facing Design
- **BrowserClient** - Abstract browser operations for testing and alternative backends
- **DOMProcessor** - Pluggable DOM processing implementations
- **ActionHandler** - Extensible action system

### Separation of Concerns
- **TabManager** - Tab operations (create, switch, close)
- **NavigationManager** - Navigation logic
- **ScreenshotManager** - Screenshot capture
- **Handlers** - Focused action implementations

### DRY (Don't Repeat Yourself)
- **ActionParams** - Reusable parameter extraction
- **JSONExtractor** - Centralized JSON parsing
- **SessionGuard** - Unified session access

### KISS (Keep It Simple, Stupid)
- Split complex methods into focused helpers
- Clear naming and single responsibility
- Minimal dependencies between modules

## ๐Ÿงช Testing

```bash
# Run all tests
cargo test

# Run with output
cargo test -- --nocapture

# Run specific test
cargo test test_browser_navigation

# Run integration tests only
cargo test --test integration
```

### Test Coverage
- **350+ tests** across all modules (all passing, 0 ignored)
- **Test files**:
  - [actor_test.rs]tests/actor_test.rs - Page, Element, Mouse, Keyboard operations
  - [browser_lifecycle_test.rs]tests/browser_lifecycle_test.rs - Browser start/stop lifecycle
  - [browser_managers_test.rs]tests/browser_managers_test.rs - Navigation, Screenshot, Tab managers
  - [browser_test.rs]tests/browser_test.rs - Browser integration
  - [cdp_enhancements_test.rs]tests/cdp_enhancements_test.rs - CDP client features
  - [dom_extraction_test.rs]tests/dom_extraction_test.rs - DOM extraction
  - [dom_test.rs]tests/dom_test.rs - DOM state and serialization
  - [error_handling_test.rs]tests/error_handling_test.rs - Error variants and propagation
  - [error_recovery_test.rs]tests/error_recovery_test.rs - Config validation and recovery
  - [integration_test.rs]tests/integration_test.rs - Action models, URL extraction, tools
  - [integration_workflow_test.rs]tests/integration_workflow_test.rs - Full workflow
  - [security_test.rs]tests/security_test.rs - Security validation
  - [tools_handlers_test.rs]tests/tools_handlers_test.rs - All action handlers
  - [tools_test.rs]tests/tools_test.rs - Tools registry
  - [traits_test.rs]tests/traits_test.rs - BrowserClient, DOMProcessor traits
  - [utils_test.rs]tests/utils_test.rs - URL extraction, signal handling
  - [agent_test.rs]tests/agent_test.rs - Agent view types
  - [agent_service_test.rs]tests/agent_service_test.rs - Agent state and history
- **Mock implementations** for deterministic testing
- **Trait-based mocking** for browser/DOM components

## โš ๏ธ Data Retention Policy

### Browser Data is NEVER Deleted

**IMPORTANT**: The `browsing` library **never deletes browser data** for safety reasons.

#### What This Means:

| Data Type | Behavior |
|-----------|----------|
| **Bookmarks** | Never deleted |
| **History** | Never deleted |
| **Cookies** | Never deleted |
| **Passwords** | Never deleted |
| **Extensions** | Never deleted |
| **Cache** | Never deleted |
| **Temp Directories** | Never deleted (left in `/tmp/`) |

#### Why This Policy Exists:

1. **User Safety**: Users may specify a custom `user_data_dir` pointing to their real browser profile
2. **Catastrophe Prevention**: Accidentally deleting a user's real browser data (bookmarks, history, passwords) would be devastating
3. **Debugging**: Leaving temp directories allows inspection after crashes or failures
4. **User Control**: Users are responsible for managing their own browser data

#### How It Works:

When no `user_data_dir` is specified:
```rust
let profile = BrowserProfile {
    user_data_dir: None,  // Uses temp directory: /tmp/browser-use-1738369200000/
    ..Default::default()
};
```

When `browser.stop()` is called:
- โœ… Browser process is killed
- โœ… In-memory state is cleared
- โŒ User data directory is **NOT** deleted

#### Managing Temporary Data:

Users are responsible for cleanup:

```bash
# List browser temp directories
ls -la /tmp/browser-use-*

# Delete old temp directories (optional, manual cleanup)
rm -rf /tmp/browser-use-1738369200000/
```

#### Using a Custom Data Directory:

```rust
let profile = BrowserProfile {
    user_data_dir: Some("/path/to/custom/profile".into()),
    ..Default::default()
};
```

**Warning**: If you point to your real browser profile, the library will NOT protect it. You're responsible for that directory.



## ๐Ÿ”ง Configuration

### Browser Profile

```rust
use browsing::BrowserProfile;

// Default: headless mode with lightweight flags
let profile = BrowserProfile::default();

// Explicit headless
let profile = BrowserProfile::default().with_headless(true);

// Visible browser for debugging
let profile = BrowserProfile::default().with_headless(false);

// With custom data directory
let profile = BrowserProfile {
    user_data_dir: Some("/path/to/profile".into()),
    ..Default::default()
};
```


## ๐Ÿ“– API Documentation

Generate and view API docs:

```bash
cargo doc --open
```