AI-Agent-First Headless Browser Engine
ByeFast is a headless browser engine built for machine intelligence, not human eyeballs. It discards the overhead of traditional browsers — pixel rendering, timing-sensitive APIs, multi-process architecture — and replaces it with a deterministic, minimal, composable engine optimised for AI agent workloads.
██████╗ ██╗ ██╗███████╗███████╗ █████╗ ███████╗████████╗
██╔══██╗╚██╗ ██╔╝██╔════╝██╔════╝██╔══██╗██╔════╝╚══██╔══╝
██████╔╝ ╚████╔╝ █████╗ █████╗ ███████║███████╗ ██║
██╔══██╗ ╚██╔╝ ██╔══╝ ██╔══╝ ██╔══██║╚════██║ ██║
██████╔╝ ██║ ███████╗██║ ██║ ██║███████║ ██║
╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝
AI-Agent-First Headless Browser Engine v0.1.0
Cold-start target: 4 ms | Idle page target: 8 MB | 1,000+ concurrent pages
| Metric | Target | Measured (Windows) | Measured (Linux) |
|---|---|---|---|
| Cold-start (internal) | ≤ 4 ms | 2.3 ms ✅ | ~1.5 ms |
| Cold-start (wall-clock) | — | 21.8 ms¹ | ~4 ms |
| Storage init (sled) | — | 7.6 ms | ~0.5 ms |
| Memory per idle page | ≤ 8 MB | ~4.1 MB ✅ | ~4.1 MB |
| Binary size (release) | ≤ 15 MB | — | — |
| Concurrent pages | 1,000+ | — | — |
| Execution model | Deterministic | ✅ | ✅ |
¹ Wall-clock includes ~12 ms Windows process-creation overhead (not attributable to ByeFast).
Internal startup time (first instruction → firstaccept()) is 2.3 ms — within the 4 ms target. Linux is treated as expected data and was not subjected to actual testing.
EventBus init 0.24 ms
Kernel 0.32 ms
ByeNet (TLS) 0.16 ms
ByeLoader 0.16 ms
ByeJS 0.16 ms
ByeSafe 0.15 ms
ByeStorage (sled) 7.64 ms ← Windows mmap cold-open
All wired 0.38 ms
TCP bind + accept 0.73 ms
──────────────────────────
Internal total 9.94 ms
Non-storage total 2.30 ms ← the real ByeFast cost
1. Use ephemeral mode for lowest latency
# Don't set BYEFAST_STORAGE_PATH — defaults to in-memory
./byefastSled database open on Windows costs ~7 ms. If you don't need persistent snapshots or cookies across restarts, skip it.
2. Use load-html instead of navigate for reliability
# navigate = async HTTP fetch + parse (may fail on bot-protected sites)
POST /pages/{id}/navigate
# load-html = synchronous, always works, zero network latency
POST /pages/{id}/load-html
{"html": "<html>..."}3. Reindex vision only when DOM changes
# Only call this after load-html or navigate, not on every find
POST /pages/{id}/vision/reindex
# Then find freely — the index is cached
POST /pages/{id}/vision/find {"intent": "checkout button"}4. Keep pages alive, don't respawn
Pages suspend automatically after 30s idle and resume instantly on next request. It's cheaper to reuse a page than destroy and spawn a new one.
# Resume a suspended page (instant)
POST /pages/{id}/resume
# Check page state before deciding to respawn
GET /pages/{id}5. Use Ghost Mode for supported sites
If the target site serves /.well-known/semantic-map.json, ByeFast skips all JS execution and DOM parsing — returning a structured element map directly. Zero JS cost.
6. Measure your own cold-start (Windows)
$start = Get-Date
Start-Process -FilePath ".\byefast.exe" -WindowStyle Minimized
do {
Start-Sleep -Milliseconds 5
$elapsed = (Get-Date) - $start
try { Invoke-WebRequest "http://localhost:8741/health" -UseBasicParsing -ErrorAction Stop | Out-Null; break } catch {}
} while ($elapsed.TotalSeconds -lt 10)
Write-Host "Ready in: $([math]::Round($elapsed.TotalMilliseconds, 1)) ms"ByeFast is a Rust workspace of 15 independent crates (~12,000 lines). All inter-engine communication flows through a single zero-copy EventBus backed by tokio::sync::broadcast. Large payloads are wrapped in Payload — an Arc<Bytes> — so cloning an event costs one atomic increment, never a memcpy.
┌──────────────────────────────────────────────────────────────┐
│ ByeAPI (axum/HTTP) │ ← LLM agent / tool-caller
└──────────────────────────┬───────────────────────────────────┘
│ HTTP/JSON port 8741
┌──────────────────────────▼───────────────────────────────────┐
│ EventBus (zero-copy broadcast) │
└──┬──────┬──────┬──────┬──────┬──────┬──────┬───────┬────────┘
│ │ │ │ │ │ │ │
┌──▼─┐ ┌──▼─┐ ┌──▼──┐ ┌▼───┐ ┌▼────┐ ┌▼────┐ ┌▼────┐ ┌▼─────┐
│Ker-│ │Net │ │Load-│ │ JS │ │ DOM │ │Lay- │ │Ren- │ │Safe │
│nel │ │ │ │er │ │ │ │ │ │out │ │der │ │ │
└────┘ └────┘ └─────┘ └────┘ └─────┘ └─────┘ └─────┘ └──────┘
Storage · Vision · Compositor · Audit · Evolve
| Crate | Lines | Role |
|---|---|---|
bye-event |
576 | Zero-copy EventBus, 30-variant Event enum, Payload |
bye-kernel |
526 | Page governor, VirtualClock, suspend/resume scheduler |
bye-dom |
982 | Flat arena DOM, built-in HTML parser, IntentEngine |
bye-net |
730 | HTTP/2+TLS, per-origin semaphore pool, response cache |
bye-loader |
551 | Priority DAG, Ghost Mode, resource discovery |
bye-js |
797 | boa_engine runtime, polyfill registry, deterministic APIs |
bye-layout |
1,123 | Incremental constraint-solver, above-fold priority |
bye-render |
588 | Neural-semantic differ, typed change events |
bye-storage |
762 | Cookie jar, IndexedDB, zstd snapshot (Web Time-Travel) |
bye-safe |
756 | Origin sandbox, capability system, HumanitySimulator |
bye-api |
1,372 | axum HTTP control surface, 32 routes, flight recorder |
bye-vision |
789 | Visual-semantic element matcher, 64-dim feature vectors |
bye-compositor |
856 | Cross-origin virtual page synthesis |
bye-audit |
827 | Cryptographic Merkle audit log |
bye-evolve |
879 | Self-healing shims and selector evolution |
Every page gets a VirtualClock. The kernel freezes it before JS executes and thaws it after. All Date.now() and performance.now() calls within a single JS invocation return the same frozen value — identical inputs always produce identical outputs.
kernel.freeze_clock(page_id)?;
// JS executes — time is frozen
kernel.thaw_clock(page_id)?;Document::from_html(html) parses raw HTML into the flat arena DOM with zero external dependencies. Handles quoted attributes, void elements, <script>/<style> skipping, HTML entities, self-closing tags, and malformed nesting.
let doc = Document::from_html("<html><body><h1 id='main'>Hello</h1></body></html>");
assert!(doc.by_id("main").is_some());
assert_eq!(doc.by_tag("h1").len(), 1);When a server provides /.well-known/semantic-map.json, the loader fetches it and skips all local JS execution entirely. The agent gets a structured element map without running any JavaScript.
When a UI update moves or renames a button, stale CSS selectors break. IntentEngine::resolve finds the new element by semantic intent — ARIA roles, visible text, labels:
let (node_id, confidence) = IntentEngine::resolve(&doc, "add to cart button")?;
// → (NodeId(7), 0.82) — found even after A/B test moved itAgents receive a typed changelog, not raw HTML. NeuralSemanticDiffer classifies DOM mutations into structured events:
SemanticChange::TextChanged { old_text: "$9.99", new_text: "$7.49", .. }
SemanticChange::ElementAppeared { role: "button", label: "Checkout now", .. }
SemanticChange::NavigationOccurred { old_url: "/cart", new_url: "/checkout" }Full page state (DOM, cookies, IndexedDB, JS globals) serialised to a zstd-compressed blob and restored on demand. Typical compression: 5–15×.
POST /pages/{id}/snapshots → { snapshot_id, compressed_bytes }
POST /pages/{id}/snapshots/{snap_id} → restores exact state
64-dimensional feature vectors built from tag, role, text, depth, and interactivity flags. Cosine similarity search with real confidence scores:
POST /pages/{id}/vision/find
{"intent": "more information link"}
→ {"node_id": 12, "tag": "a", "text": "More information...", "confidence": 0.82}
Every agent action recorded into a Merkle-tree audit log. Verifiable proofs for individual actions:
GET /pages/{id}/audit/session/{sid}/prove/{action_id}
→ { "root_hex": "...", "merkle_proof": { "leaf_hex": "...", "path": [...] } }
Compose multiple real pages into a single virtual page with a unified query surface. Mount/unmount real pages into named slots and dispatch actions across all of them.
Observes polyfill failures and broken selectors, then generates repaired versions:
POST /pages/{id}/evolve/repair/{api} → repaired polyfill shim
POST /pages/{id}/evolve/selector → evolved CSS selector
GET /pages/{id}/evolve/health → failure/repair statistics
Generates Bézier-curved mouse paths and keystroke timing distributions matching Fitts' Law measurements, defeating headless-browser fingerprinting:
let path = safe.mouse_path(0.0, 0.0, 350.0, 280.0, now_ms, page_id);
let timings = safe.keystroke_timings("hello", now_ms, page_id);Web APIs loaded on first use. Available: fetch, URL, TextEncoder, TextDecoder, structuredClone. A ReferenceError triggers load-and-retry automatically.
document.querySelector("h1") // → { id, tagName, innerText }
document.querySelectorAll("a") // → array of node objects
document.open() // begin write buffer
document.write("<html>...") // append HTML
document.close() // flush buffer → parse into live DOM
document.title() // → "Page Title"Server runs on port 8741 by default.
| Method | Path | Description |
|---|---|---|
POST |
/pages |
Spawn page |
GET |
/pages |
List all pages |
GET |
/pages/{id} |
Status + VirtualClock |
DELETE |
/pages/{id} |
Destroy page |
POST |
/pages/{id}/navigate |
Navigate to URL (auto-fetches + parses HTML) |
POST |
/pages/{id}/load-html |
Inject raw HTML directly |
POST |
/pages/{id}/resume |
Resume suspended page |
POST |
/pages/{id}/clock/advance |
Advance VirtualClock |
| Method | Path | Description |
|---|---|---|
GET |
/pages/{id}/semantic-action-map |
All elements, links, forms |
POST |
/pages/{id}/actions |
click / type / scroll / hover |
POST |
/pages/{id}/eval |
Execute JavaScript |
GET |
/pages/{id}/console |
Console output |
| Method | Path | Description |
|---|---|---|
POST |
/pages/{id}/vision/find |
Find element by natural-language intent |
POST |
/pages/{id}/vision/find-interactive |
Find interactive element by intent |
POST |
/pages/{id}/vision/reindex |
Rebuild vision index |
| Method | Path | Description |
|---|---|---|
GET |
/pages/{id}/capabilities |
List granted capabilities |
POST |
/pages/{id}/capabilities/request |
Request grants |
Available: Clipboard Geolocation MediaDevices Notifications PersistentStorage PopupWindows WebAssembly WebGL WebAudio IndexedDb SemanticActionMap Screenshot
| Method | Path | Description |
|---|---|---|
POST |
/pages/{id}/snapshots |
Save state |
GET |
/pages/{id}/snapshots |
List snapshots |
POST |
/pages/{id}/snapshots/{snap_id} |
Restore state |
| Method | Path | Description |
|---|---|---|
GET/POST |
/compositor/pages |
List / create virtual pages |
GET/DELETE |
/compositor/pages/{vp_id} |
Query / destroy |
POST/DELETE |
/compositor/pages/{vp_id}/slots |
Mount / unmount slot |
POST |
/compositor/pages/{vp_id}/actions |
Cross-slot action |
| Method | Path | Description |
|---|---|---|
POST |
/pages/{id}/audit/session |
Start session |
GET/DELETE |
/pages/{id}/audit/session/{sid} |
Summary / end |
POST |
/pages/{id}/audit/session/{sid}/record |
Record action |
GET |
/pages/{id}/audit/session/{sid}/prove/{aid} |
Merkle proof |
GET |
/pages/{id}/audit/session/{sid}/log |
Full log |
| Method | Path | Description |
|---|---|---|
POST |
/pages/{id}/evolve/repair/{api} |
Repair polyfill |
POST |
/pages/{id}/evolve/selector |
Evolve selector |
GET |
/pages/{id}/evolve/health |
Health report |
| Method | Path | Description |
|---|---|---|
GET |
/pages/{id}/trace |
Full event log |
GET |
/health |
Engine health |
GET |
/stats |
Pages, storage, bus metrics |
| Variable | Default | Description |
|---|---|---|
BYEFAST_ADDR |
0.0.0.0:8741 |
Bind address |
BYEFAST_STORAGE_PATH |
(ephemeral) | Sled DB path; omit for in-memory |
BYEFAST_MAX_PAGES |
1000 |
Max concurrent pages |
BYEFAST_LOG |
byefast=info,... |
tracing filter |
Prerequisites: Rust 1.75+ (2021 edition). No C dependencies.
# Build
cargo build --release
# Run
./target/release/byefast
# Test
cargo test --workspaceQuick start:
# Spawn a page
curl -X POST http://localhost:8741/pages \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
# Inject HTML
curl -X POST http://localhost:8741/pages/$PAGE/load-html \
-H "Content-Type: application/json" \
-d '{"html":"<html><head><title>Test</title></head><body><h1>Hello</h1><a href=\"/about\">About</a></body></html>"}'
# Read semantic map
curl http://localhost:8741/pages/$PAGE/semantic-action-map
# Find element by intent
curl -X POST http://localhost:8741/pages/$PAGE/vision/find \
-H "Content-Type: application/json" \
-d '{"intent":"about link"}'byefast/
├── Cargo.toml
├── crates/
│ ├── bye-event/ # Zero-copy EventBus + 30-variant Event enum
│ ├── bye-kernel/ # Page governor + VirtualClock
│ ├── bye-dom/ # Flat arena DOM + built-in HTML parser + IntentEngine
│ ├── bye-net/ # HTTP/2 network stack
│ ├── bye-loader/ # Priority DAG + Ghost Mode
│ ├── bye-js/ # boa_engine runtime + polyfills + document bindings
│ ├── bye-layout/ # Incremental layout engine
│ ├── bye-render/ # Neural-semantic differ
│ ├── bye-storage/ # Cookies + IndexedDB + zstd Web Time-Travel
│ ├── bye-safe/ # Sandbox + capability system + HumanitySimulator
│ ├── bye-api/ # axum HTTP control surface (32 routes)
│ ├── bye-vision/ # Visual-semantic element matcher
│ ├── bye-compositor/ # Cross-origin virtual page synthesis
│ ├── bye-audit/ # Cryptographic Merkle audit log
│ └── bye-evolve/ # Self-healing shims + selector evolution
├── bin/byefast/ # Entry point
└── tests/ # Integration suite
No Serialisation Tax. Engine communication uses Payload (Arc<Bytes>). No JSON on the hot path between internal components.
Lazy Everything. Pages that only use fetch never pay for WebGL, WebRTC, or Web Audio.
Deterministic Replay. VirtualClock + EventBus log = any page can be replayed exactly.
Typed Errors, Never Silent Failures. Structured events on the bus. Agents receive errors they can act on.
Isolation First. A JS crash in page A is a PageDestroyed { reason: JsCrash } event. Page B is unaffected.
MIT