### Run the getting started example Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-rust.md Execute the provided example using the cargo run command. ```bash cargo run --release -p browser_oxide --example getting_started -- https://example.com ``` -------------------------------- ### Install BrowserOxide from source Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-python.md Builds the Rust engine and installs the wheel using maturin. ```bash python -m venv .venv && source .venv/bin/activate pip install maturin maturin develop --release # builds the Rust engine + installs the wheel ``` -------------------------------- ### Install BrowserOxide via pip Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-python.md Standard installation command for the Python package. ```bash pip install browser-oxide # once published to PyPI ``` -------------------------------- ### Clone and Build Project Source: https://github.com/yfedoseev/browser_oxide/blob/main/CONTRIBUTING.md Initial setup commands to clone the repository and build the workspace. ```bash git clone https://github.com/yfedoseev/browser_oxide cd browser_oxide cargo build --workspace cargo test --workspace -- --test-threads=1 ``` -------------------------------- ### Install browser-oxide-mcp via Cargo Source: https://github.com/yfedoseev/browser_oxide/blob/main/crates/browser_oxide_mcp/README.md Use this command to install the MCP server binary from the GitHub repository. ```bash cargo install --git https://github.com/yfedoseev/browser_oxide browser_oxide_mcp ``` -------------------------------- ### Run sweep_metrics example Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CONFIGURATION.md Executes the sweep_metrics example using cargo with specified profile, corpus, and output files. ```bash cargo run --release -p browser_oxide --example sweep_metrics -- ``` -------------------------------- ### Install BrowserOxide Dependencies Source: https://github.com/yfedoseev/browser_oxide/blob/main/llms.txt Installation commands for integrating BrowserOxide into Rust, Python, and MCP environments. ```toml browser = { git = "https://github.com/yfedoseev/browser_oxide" } ``` ```bash pip install browser-oxide ``` ```bash cargo install --git https://github.com/yfedoseev/browser_oxide browser_oxide_mcp ``` -------------------------------- ### Start CDP server Source: https://github.com/yfedoseev/browser_oxide/blob/main/README.md Start a CDP server to allow Puppeteer or Playwright to connect to the engine. ```rust use protocol::CdpServer; let server = CdpServer::start_navigable(9222)?; // Connect with Puppeteer to ws://127.0.0.1:9222 ``` -------------------------------- ### Start a CDP server in Rust Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/CDP.md Initializes a CDP server instance. Use start_ephemeral for an OS-assigned port or specify a port for static binding. ```rust use protocol::CdpServer; // empty page, ready for the client's Page.navigate: let server = CdpServer::start_navigable(9222)?; println!("connect to ws://127.0.0.1:{}", server.port()); // or seed it with a URL / HTML: let server = CdpServer::start_with_url("https://example.com", 9222)?; let server = CdpServer::start("

hi

", 9222)?; let server = CdpServer::start_ephemeral("

hi

")?; // OS-assigned port ``` -------------------------------- ### Web Worker Communication Example Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/WORKERS.md Demonstrates creating a worker, sending messages, and handling responses in both the main page and the worker script. ```javascript // Page creates a worker const worker = new Worker('/worker.js'); worker.postMessage({ type: 'compute', data: payload }); worker.onmessage = (e) => console.log(e.data); worker.terminate(); // Inside worker.js self.onmessage = (e) => { const result = heavyComputation(e.data); self.postMessage(result); }; ``` -------------------------------- ### CSS Nesting Syntax Example Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_PARSER.md Demonstrates the structure of nested CSS rules, including parent selectors, implicit nesting, and nested at-rules, which the parser must handle. ```css .card { color: black; /* Nested rule — & refers to parent selector */ & .title { font-weight: bold; } /* Implicit nesting (starts with combinator/selector) */ .title { font-weight: bold; } /* Nested at-rule */ @media (width > 768px) { padding: 2rem; } /* Deeply nested */ &:hover { color: blue; & .icon { opacity: 1; } } } ``` -------------------------------- ### CDP Wire Format Examples Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/PROTOCOL.md JSON-RPC message structures for requests, responses, and events over WebSocket. ```json // Request (client → BrowserOxide) {"id": 1, "method": "Page.navigate", "params": {"url": "https://example.com"}} // Response (BrowserOxide → client) {"id": 1, "result": {"frameId": "main", "loaderId": "loader1"}} // Event (BrowserOxide → client, no id) {"method": "Page.loadEventFired", "params": {"timestamp": 1234567890.123}} ``` -------------------------------- ### JavaScript Layout API Usage Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/LAYOUT.md Examples of common DOM layout API calls used by frameworks and anti-bot systems. ```javascript // SPA frameworks (React, Vue) check element dimensions const rect = element.getBoundingClientRect(); if (rect.width === 0) { /* element not visible, skip */ } // Anti-bot checks (visibility verification) const nav = document.querySelector('nav'); if (nav.offsetHeight === 0) { /* suspicious — bot doesn't have layout */ } // Lazy loading if (entry.isIntersecting) { loadImage(); } ``` -------------------------------- ### Initialize with Built-in Presets Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/STEALTH.md Use pre-verified identity presets to navigate pages with stealth settings. ```rust use browser::Page; let profile = stealth::presets::chrome_148_macos(); let page = Page::navigate_stealth("https://example.com", profile).await?; ``` -------------------------------- ### Protocol Negotiation Sequence Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/NETWORKING.md The step-by-step process for establishing connections, including DNS lookup, QUIC/HTTP3 attempts, and fallback to TCP/TLS. ```text 1. DNS lookup (may include HTTPS record with ALPN hint) 2. If QUIC/HTTP3 previously succeeded for this origin: → Try QUIC connection (0-RTT if possible) → Fall back to TCP if QUIC fails 3. Else: → TCP + TLS handshake → ALPN negotiates h2 (HTTP/2) or http/1.1 → HTTP/2 SETTINGS exchange 4. Alt-Svc header may advertise HTTP/3 for future requests ``` -------------------------------- ### Scrape multiple URLs Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-python.md Example of iterating through a list of URLs using a single browser instance. ```python from browser_oxide import Browser, Profile, Verdict URLS = ["https://example.com", "https://news.ycombinator.com"] with Browser(profile=Profile.chrome()) as b: for url in URLS: page = b.navigate(url) status = "ok" if page.verdict == Verdict.PASS else page.verdict print(f"{status:18} {len(page.html):>8} {page.title}") ``` -------------------------------- ### Initialize browser engine in Python Source: https://github.com/yfedoseev/browser_oxide/blob/main/README.md Use the Browser context manager to navigate and evaluate pages in Python. ```python from browser_oxide import Browser, Profile, Verdict with Browser(profile=Profile.chrome()) as b: page = b.navigate("https://example.com") print(page.title, len(page.html), page.verdict) if page.verdict == Verdict.PASS: print(page.evaluate("navigator.userAgent")) ``` -------------------------------- ### Run build and test commands Source: https://github.com/yfedoseev/browser_oxide/blob/main/AGENTS.md Standard commands for building, testing, and linting the workspace. Note that tests must run single-threaded due to V8 isolate constraints. ```bash cargo build --workspace cargo test --workspace -- --test-threads=1 # V8 isolates are per-thread cargo clippy --all-targets --workspace -- -D warnings # GATING: warnings = errors cargo fmt --all -- --check cargo doc --no-deps --workspace ``` -------------------------------- ### Compute element styles with StyleEngine Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_CASCADE.md Initialize the engine with viewport and media features, add stylesheets, and compute styles for specific DOM elements. ```rust use css_cascade::{StyleEngine, ComputedStyle}; let mut engine = StyleEngine::new(viewport, media_features); // Add stylesheets (parsed by css_parser) engine.add_stylesheet(user_agent_styles, Origin::UserAgent); engine.add_stylesheet(page_styles, Origin::Author); // Compute style for an element let style = engine.compute_style(&dom, element_id); assert_eq!(style.display(), Display::Flex); assert_eq!(style.color(), Color::Rgb(0, 0, 0)); assert_eq!(style.get_custom_property("--spacing"), Some("1rem")); ``` -------------------------------- ### Run Development Gates Source: https://github.com/yfedoseev/browser_oxide/blob/main/CONTRIBUTING.md Commands to verify code quality and formatting before pushing changes. ```bash cargo fmt --all -- --check cargo clippy --workspace -- -D warnings cargo test --workspace -- --test-threads=1 cargo doc --no-deps --workspace ``` -------------------------------- ### Reuse browser isolates with PagePool Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-rust.md Use PagePool to amortize the cost of V8 isolate setup. Note that the pool is intended for high-throughput benign pages and should be avoided for protected targets requiring challenge-follow loops. ```rust let pool = browser::PagePool::new(4); let mut page = pool.navigate("https://example.com", profile).await?; let html = page.content(); pool.release(page); // return the isolate to the pool for reuse ``` -------------------------------- ### Python SDK: Browser Navigation Source: https://github.com/yfedoseev/browser_oxide/blob/main/llms.txt Methods for initializing a browser session and navigating to URLs. ```APIDOC ## Browser Initialization ### Method `Browser(profile=Profile.chrome())` ### Description Initializes a browser instance. This is context-managed and spawns the engine thread. ## Navigate ### Method `b.navigate(url, max_iterations=5) -> Page` ### Description Navigates to the specified URL. The GIL is released during the call. ### Parameters - **url** (string) - Required - The URL to navigate to. - **max_iterations** (int) - Optional - Maximum iterations for navigation. ``` -------------------------------- ### Initialize BrowserOxide on a current-thread runtime Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-rust.md Use a LocalSet with a current-thread Tokio runtime to manage the !Send browser engine. ```rust use browser::{ChallengeVerdict, Page}; fn main() { let rt = tokio::runtime::Builder::new_current_thread() .enable_all().build().unwrap(); let local = tokio::task::LocalSet::new(); local.block_on(&rt, async { let profile = stealth::presets::chrome_148_macos(); let mut page = Page::navigate("https://example.com", profile, 5).await.unwrap(); println!("{}", page.title()); // document.title println!("{} bytes", page.content().len()); // outerHTML println!("{}", page.evaluate("navigator.userAgent").unwrap()); match page.challenge_verdict() { ChallengeVerdict::Pass => println!("real content"), v if v.is_challenge() => println!("blocked: {}", v.as_str()), v => println!("{}", v.as_str()), // thin shell / render-incomplete } }); } ``` -------------------------------- ### Initialize browser engine in Rust Source: https://github.com/yfedoseev/browser_oxide/blob/main/README.md Run the engine on a current-thread runtime with LocalSet, as V8 isolates are per-thread. ```rust use browser::{ChallengeVerdict, Page}; fn main() { let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap(); tokio::task::LocalSet::new().block_on(&rt, async { let profile = stealth::presets::chrome_148_macos(); // built-in identity let mut page = Page::navigate("https://example.com", profile, 5).await.unwrap(); println!("{}", page.title()); println!("{}", page.evaluate("document.querySelectorAll('a').length").unwrap()); // challenge pages return HTTP 200 — trust the verdict, not the status: if page.challenge_verdict() == ChallengeVerdict::Pass { println!("real content rendered"); } }); } ``` -------------------------------- ### Add BrowserOxide dependencies Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-rust.md Configure Cargo.toml to include the browser and stealth crates from the git repository. ```toml # Cargo.toml [dependencies] browser = { git = "https://github.com//browser_oxide" } # the top-level API stealth = { git = "https://github.com//browser_oxide" } # browser profiles tokio = { version = "1", features = ["rt", "macros"] } ``` -------------------------------- ### Navigate and Interact with BrowserOxide Source: https://github.com/yfedoseev/browser_oxide/blob/main/python/README.md Initialize a browser session with a profile, navigate to a URL, and evaluate JavaScript or query page elements. ```python from browser_oxide import Browser, Profile, Verdict with Browser(profile=Profile.chrome()) as b: page = b.navigate("https://example.com") print(page.title, len(page.html), page.verdict) if page.verdict == Verdict.PASS: # challenge pages return HTTP 200 — print(page.evaluate("navigator.userAgent")) # trust the verdict, not status print(page.query_text("h1")) ``` -------------------------------- ### Project Directory Structure Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/PROTOCOL.md Visual representation of the protocol crate organization and source file locations. ```text protocol/ ├── src/ │ ├── lib.rs # CdpServer — accepts WebSocket connections │ ├── server.rs # WebSocket server (tokio-tungstenite) │ ├── session.rs # Per-connection session state │ ├── router.rs # Method dispatch (domain.method → handler) │ ├── types.rs # CDP JSON types (auto-generated from protocol.json) │ ├── domains/ │ │ ├── target.rs # Target domain handlers │ │ ├── page.rs # Page domain handlers │ │ ├── runtime.rs # Runtime domain handlers │ │ ├── dom.rs # DOM domain handlers │ │ ├── network.rs # Network domain handlers │ │ ├── fetch.rs # Fetch domain handlers │ │ ├── input.rs # Input domain handlers │ │ └── emulation.rs # Emulation domain handlers │ └── codegen/ # Generate Rust types from Chrome's protocol.json │ ├── protocol.json # Official CDP protocol definition │ └── generate.rs # Build script: JSON → Rust structs ├── tests/ │ ├── puppeteer_compat.rs # Run Puppeteer test suite against our server │ └── playwright_compat.rs └── Cargo.toml ``` -------------------------------- ### Tokenizer::new Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_PARSER.md Initializes a new tokenizer to process CSS source code into individual tokens. ```APIDOC ## Tokenizer::new ### Description Creates a new tokenizer instance for the provided CSS input string. ### Signature `Tokenizer::new(input: &str) -> Tokenizer` ``` -------------------------------- ### Display Workspace Directory Structure Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/ARCHITECTURE.md Visual representation of the project's crate-based architecture. ```text browser_oxide/ ├── Cargo.toml # Workspace root ├── crates/ │ ├── css_parser/ # CSS Syntax Level 3 tokenizer + parser (+ nesting) │ ├── css_selectors/ # Selectors Level 4 parser + matcher │ ├── css_values/ # CSS property value parsing + computed values │ ├── css_cascade/ # Cascade, specificity, inheritance, @layer, @media │ ├── dom/ # Mutable DOM tree + Web API interfaces + Shadow DOM │ ├── html_parser/ # html5ever integration + TreeSink → DOM │ ├── js_runtime/ # V8 engine (rusty_v8) + DOM bindings + WASM │ ├── canvas/ # Canvas 2D API (tiny-skia backend) + WebGL stubs │ ├── layout/ # Box model via taffy (getBoundingClientRect) │ ├── net/ # HTTP/1.1 + HTTP/2 + HTTP/3 + stealth TLS + cookies │ ├── event_loop/ # Timers, microtasks, Promises, rAF │ ├── workers/ # Web Workers + Service Workers (separate V8 isolates) │ ├── stealth/ # Fingerprint profiles + navigator spoofing │ ├── protocol/ # CDP server (Puppeteer/Playwright compat) │ └── browser/ # Top-level Browser/Page/Context + iframes ├── tests/ # Integration tests ├── benches/ # Benchmarks vs Chrome headless, Lightpanda └── docs/ # This documentation ``` -------------------------------- ### Deno Core and Tokio Integration Diagram Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/EVENT_LOOP.md Visual representation of the relationship between the tokio runtime, JsRuntime, and the BrowserEventLoop. ```text tokio runtime └── deno_core JsRuntime ├── V8 Isolate (JS execution + WASM) ├── Op futures (Rust async ops callable from JS) ├── V8 microtask checkpoint (after each op resolves) └── Module loading (ES modules fetched async) └── BrowserEventLoop (wraps JsRuntime) ├── Timer scheduling (setTimeout/setInterval) ├── rAF simulation (16.67ms ticks) ├── requestIdleCallback └── Idle detection (network quiescence + timer drain) ``` -------------------------------- ### Configure MCP server in JSON Source: https://github.com/yfedoseev/browser_oxide/blob/main/crates/browser_oxide_mcp/README.md Add this configuration to your MCP client settings to register the browser-oxide server. ```json { "mcpServers": { "browser-oxide": { "command": "browser-oxide-mcp" } } } ``` -------------------------------- ### Build and test the workspace Source: https://github.com/yfedoseev/browser_oxide/blob/main/llms.txt Compiles the entire workspace and executes tests. Tests must be run with a single thread because V8 isolates are bound to specific threads. ```bash cargo build --workspace cargo test --workspace -- --test-threads=1 # V8 isolates are per-thread ``` -------------------------------- ### Resolve Custom Properties Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_CASCADE.md Demonstrates var() substitution with fallbacks and nested variables. ```css :root { --spacing: 1rem; } .box { padding: var(--spacing); } /* → 1rem */ .box { padding: var(--missing, 0.5rem); } /* → 0.5rem (fallback) */ .box { padding: var(--a, var(--b, 1px)); } /* → nested fallback */ ``` -------------------------------- ### V8 Isolate Lifecycle Steps Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/JS_RUNTIME.md The sequential process for managing a V8 isolate from creation to destruction. ```text 1. Create V8 Isolate (or restore from snapshot) 2. Create Context with global object template 3. Populate globals (window, document, navigator, ...) 4. Execute page scripts 5. Run event loop (timers, fetch callbacks, WASM) 6. Extract content 7. Destroy Isolate (all JS objects freed) ``` -------------------------------- ### Page::navigate_with_solvers Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/CHALLENGES.md Navigates to a URL using a custom set of challenge solvers to handle anti-bot interstitials. ```APIDOC ## Page::navigate_with_solvers(url, profile, timeout, solvers) ### Description Navigates to a URL while utilizing registered ChallengeSolver implementations to automatically handle and resolve anti-bot challenges. ### Parameters - **url** (string) - Required - The target URL. - **profile** (BrowserProfile) - Required - The browser profile to use. - **timeout** (u32) - Required - Navigation timeout in seconds. - **solvers** (Arc<[Arc]>) - Required - A collection of custom solvers to execute during navigation. ``` -------------------------------- ### Use CSS Parser API Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_PARSER.md Demonstrates low-level tokenization and high-level parsing of stylesheets, declaration lists, and component values. ```rust use css_parser::{Tokenizer, Token, Parser, Stylesheet, Rule}; // Low-level: tokenize let mut tokenizer = Tokenizer::new("h1 { color: red; }"); for token in &mut tokenizer { println!("{:?}", token); } // High-level: parse stylesheet let stylesheet = Parser::parse_stylesheet(css_source)?; for rule in &stylesheet.rules { match rule { Rule::Qualified(qr) => { println!("selector: {:?}", qr.prelude); println!("declarations: {:?}", qr.declarations); println!("nested rules: {:?}", qr.rules); // nested! } Rule::At(at) => { println!("@{} ...", at.name); } } } // Parse inline style attribute let decls = Parser::parse_declaration_list("color: red; font-size: 16px")?; // Parse a single component value let value = Parser::parse_component_value("rgb(255, 0, 0)")?; ``` -------------------------------- ### Visualize the CSS Value Resolution Pipeline Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_VALUES.md A diagram illustrating the flow from raw CSS text through parsing and cascade to final layout values. ```text Raw CSS text │ css_parser ▼ Component values (tokens) │ css_values ▼ Specified values (typed, per property) │ css_cascade (inheritance, var() resolution) ▼ Computed values (absolute, resolved) │ layout ▼ Used values (after layout) ``` -------------------------------- ### View the css_values Crate Architecture Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_VALUES.md A directory structure overview of the crate's organization, separating property definitions, parsing logic, and type implementations. ```text css_values/ ├── src/ │ ├── lib.rs │ ├── property.rs # PropertyValue enum (one variant per property) │ ├── parse.rs # Property name → parser dispatch │ ├── types/ │ │ ├── length.rs # Length, LengthPercentage, calc() │ │ ├── color.rs # Color (all color spaces + color-mix) │ │ ├── display.rs # Display values │ │ ├── position.rs # Position values │ │ ├── flex.rs # Flex shorthand/longhands │ │ ├── grid.rs # Grid values │ │ ├── font.rs # Font shorthand/longhands │ │ ├── transform.rs # Transform functions │ │ ├── custom.rs # var(), env(), custom properties │ │ └── shorthands.rs # Shorthand → longhand expansion │ └── resolve.rs # var() substitution, calc() evaluation └── Cargo.toml ``` -------------------------------- ### Navigate and inspect pages Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/getting-started-python.md Basic usage of the Browser context manager to navigate and inspect page properties. ```python from browser_oxide import Browser, Profile, Verdict with Browser(profile=Profile.chrome()) as b: page = b.navigate("https://example.com") print(page.title) # "Example Domain" print(len(page.html)) # rendered outerHTML length print(page.verdict) # "pass" / "thin-shell" / "edge-block" / ... if page.verdict == Verdict.PASS: print(page.evaluate("navigator.userAgent")) print(page.query_text("h1")) ``` -------------------------------- ### Crate Dependency Graph Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/ARCHITECTURE.md Visual representation of the crate hierarchy and module relationships within the browser engine. ```text ┌──────────┐ │ browser │ ← top-level API + iframe contexts └────┬─────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ┌────▼────┐ ┌────────▼────────┐ ┌──────▼──────┐ │protocol │ │ js_runtime │ │ stealth │ │ (CDP) │ │ (V8 + WASM) │ └─────────────┘ └─────────┘ └────────┬────────┘ │ ┌────────────┼──────────────┬────────────┐ │ │ │ │ ┌─────▼──┐ ┌────▼───┐ ┌──────▼─────┐ ┌───▼─────┐ │ dom │ │ canvas │ │ event_loop │ │ workers │ │+shadow │ │(skia) │ └────────────┘ └─────────┘ └───┬────┘ └────────┘ │ ┌────────┼──────────┐ │ │ │ ┌──▼─────┐┌─▼────┐┌───▼──────┐ │html ││css ││css │ │_parser ││_sel. ││_cascade │ └────────┘└──────┘└───┬──────┘ │ ┌──────▼──────┐ │ css_values │ └──────┬──────┘ │ ┌──────▼──────┐ │ css_parser │ └─────────────┘ ┌─────────────┐ ┌────────┐ │ net │ │ layout │ │ (HTTP/1+2+3)│ │(taffy) │ └─────────────┘ └────────┘ ``` -------------------------------- ### Apply Container Queries Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_CASCADE.md Define a container type and use @container to apply styles based on the ancestor's size. ```css .card-container { container-type: inline-size; } @container (min-width: 400px) { .card { flex-direction: row; } } ``` -------------------------------- ### Implement Custom ChallengeSolver Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/CHALLENGES.md Define a custom solver by implementing the ChallengeSolver trait and registering it with navigate_with_solvers. ```rust use browser::{ChallengeKind, ChallengeSolver, SolveOutcome, Page}; struct MySolver; #[async_trait::async_trait(?Send)] // !Send: runs on the engine thread impl ChallengeSolver for MySolver { fn name(&self) -> &'static str { "my-vendor" } // Identify the challenge from the response/body. fn detect(&self, resp: &net::Response, html: &str) -> Option { html.contains("my_marker").then(|| ChallengeKind::new("my-vendor", "type-a")) } // Do the work; return Solved to make the engine refetch the URL. async fn solve(&self, page: &mut Page, client: &net::HttpClient, kind: ChallengeKind) -> SolveOutcome { // ... acquire a clearance cookie / run the PoW / round-trip the interstitial ... SolveOutcome::Solved } } let solvers: std::sync::Arc<[std::sync::Arc]> = std::sync::Arc::from(vec![std::sync::Arc::new(MySolver) as _]); let mut page = Page::navigate_with_solvers(url, profile, 5, solvers).await?; ``` -------------------------------- ### Run thin_probe for SPA debugging Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/DEBUGGING.md Use this probe to diagnose thin or shell-only renders by capturing script errors and document state. ```bash cargo run --release -p browser_oxide --example thin_probe -- https://example.com chrome_148_macos # run a probe expression after nav and dump the body: PROBE_JS='(async()=>document.querySelectorAll("*").length)()' \ DUMP_BODY=/tmp/body.html \ cargo run --release -p browser_oxide --example thin_probe -- ``` -------------------------------- ### Load StealthProfile from file Source: https://github.com/yfedoseev/browser_oxide/blob/main/README.md Load a browser identity from a YAML or JSON file to configure UA string, screen, locale, and TLS impersonation. ```rust use stealth::StealthProfile; let profile = StealthProfile::load_from_file("profiles/chrome_148_macos.yaml")?; profile.validate()?; let mut page = Page::navigate("https://example.com", profile, 5).await?; ``` -------------------------------- ### StyleEngine API Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/CSS_CASCADE.md The StyleEngine is the primary entry point for managing stylesheets and computing styles for elements. ```APIDOC ## StyleEngine ### Description The `StyleEngine` is used to manage stylesheets and compute the final style for a specific DOM element. ### Methods - **StyleEngine::new(viewport, media_features)**: Initializes a new style engine instance. - **engine.add_stylesheet(stylesheet, origin)**: Adds a parsed stylesheet to the engine with a specified origin (e.g., UserAgent, Author). - **engine.compute_style(&dom, element_id)**: Computes the style for a given element within the provided DOM. ### Example ```rust let mut engine = StyleEngine::new(viewport, media_features); engine.add_stylesheet(user_agent_styles, Origin::UserAgent); engine.add_stylesheet(page_styles, Origin::Author); let style = engine.compute_style(&dom, element_id); ``` ``` -------------------------------- ### Accessing Built-in Browser Presets Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/PROFILES.md Use the presets module to select specific browser identities for desktop or mobile environments, or apply locale overrides. ```rust use stealth::presets; // Desktop — Chrome 148 (primary; current stable as of mid-2026) presets::chrome_148_macos(); presets::chrome_148_windows(); presets::chrome_148_linux(); presets::chrome_148_ru(); presets::chrome_148_cn(); presets::chrome_148_de(); presets::chrome_148_jp(); // Desktop — Firefox 135 (real NSS ClientHello, not Chrome-on-wire) presets::firefox_135_macos(); presets::firefox_135_windows(); presets::firefox_135_linux(); // Mobile presets::pixel_9_pro_chrome_148(); // Android + Chrome presets::iphone_15_pro_safari_18(); // iOS + Safari // Helpers presets::with_locale(profile, "de-DE"); // override language/timezone coherently presets::random_desktop(); // a random desktop preset ``` -------------------------------- ### Run fetch_probe for network diagnostics Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/guides/DEBUGGING.md Isolate transport or TLS issues by performing raw HTTP requests through the stealth network stack. ```bash cargo run --release -p browser_oxide --example fetch_probe -- https://example.com ``` -------------------------------- ### Define a custom browser profile in YAML Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/STEALTH.md Use this structure to define browser and OS fingerprinting attributes. Omitted fields will fall back to default values provided by serde. ```yaml # Chrome 148 on Windows 11, 1080p, en-GB user_agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36" browser_name: "Chrome" browser_version: "148.0.7778.168" os_name: "Windows" os_version: "10.0.0" platform: "Win32" vendor: "Google Inc." vendor_sub: "" product_sub: "20030107" app_version: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36" screen_width: 1920 screen_height: 1080 screen_avail_width: 1920 screen_avail_height: 1032 screen_avail_top: 0 screen_color_depth: 24 device_pixel_ratio: 1.0 cpu_cores: 16 device_memory: 8 max_touch_points: 0 webgl_vendor: "Google Inc. (NVIDIA)" webgl_renderer: "ANGLE (NVIDIA, NVIDIA GeForce RTX 3060 Direct3D11 vs_5_0 ps_5_0, D3D11)" language: "en-GB" languages: ["en-GB", "en"] timezone: "Europe/London" cpu_architecture: "x86" cpu_bitness: "64" platform_version: "15.0.0" tls_impersonate: "chrome_147" connection_effective_type: "4g" connection_rtt: 50 connection_downlink: 10.0 pdf_viewer_enabled: true plugins_count: 5 mime_types_count: 2 canvas_seed: 123456789 audio_seed: 987654321 prefers_color_scheme: "light" pointer_type: "fine" hover_capability: "hover" inner_width: 1920 inner_height: 953 outer_width: 1920 outer_height: 1032 ``` -------------------------------- ### Cite BrowserOxide Source: https://github.com/yfedoseev/browser_oxide/blob/main/README.md Use this BibTeX entry to cite the BrowserOxide project in academic or software documentation. ```bibtex @software{browseroxide, title = {BrowserOxide: A From-Scratch Stealth Headless Browser Engine in Rust}, author = {Yury Fedoseev}, year = {2026}, url = {https://github.com/yfedoseev/browser_oxide} } ``` -------------------------------- ### Measure BrowserOxide Peak RSS Source: https://github.com/yfedoseev/browser_oxide/blob/main/docs/MEMORY.md Uses /proc//status to track the peak resident set size (VmHWM) of the BrowserOxide process. ```bash cargo build --release -p browser_oxide --example thin_probe target/release/examples/thin_probe https://en.wikipedia.org/wiki/Web_scraping & pid=$!; peak=0 while kill -0 $pid 2>/dev/null; do hwm=$(awk '/VmHWM/{print $2}' /proc/$pid/status 2>/dev/null) [ -n "$hwm" ] && [ "$hwm" -gt "$peak" ] && peak=$hwm sleep 0.05 done echo "BrowserOxide peak RSS: $((peak/1024)) MB" ```