Rom
A browser-like runtime in Rust, built without Chromium. ROM composes an embedded JavaScript engine, browser-facing host objects, and a compatibility-driven runtime for deterministic web automation, surface emulation, and browser API research.
Install / Use
/learn @Rxflex/RomREADME
ROM
<p align="center"> <img src="./assets/rom-stack.svg" alt="ROM architecture overview" width="920" /> </p> <p align="center"> <strong>A browser-like runtime in Rust, built without Chromium.</strong><br/> ROM composes an embedded JavaScript engine, browser-facing host objects, and a compatibility-driven runtime for deterministic web automation, surface emulation, and browser API research. </p> <p align="center"> <a href="https://github.com/Rxflex/rom/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/Rxflex/rom/actions/workflows/ci.yml/badge.svg"></a> <a href="https://github.com/Rxflex/rom/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/Rxflex/rom?style=for-the-badge&logo=github&color=111827&labelColor=0f172a"></a> <a href="https://github.com/Rxflex/rom/network/members"><img alt="GitHub forks" src="https://img.shields.io/github/forks/Rxflex/rom?style=for-the-badge&logo=github&color=111827&labelColor=0f172a"></a> <a href="https://github.com/Rxflex/rom/issues"><img alt="GitHub issues" src="https://img.shields.io/github/issues/Rxflex/rom?style=for-the-badge&logo=github&color=111827&labelColor=0f172a"></a> <a href="https://github.com/Rxflex/rom/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/github/license/Rxflex/rom?style=for-the-badge&color=111827&labelColor=0f172a"></a> </p> <p align="center"> <img alt="Rust 2024 edition" src="https://img.shields.io/badge/Rust-2024%20edition-b7410e?style=flat-square&logo=rust"> <img alt="Runtime focus" src="https://img.shields.io/badge/Focus-browser%20emulation-0f766e?style=flat-square"> <img alt="Status" src="https://img.shields.io/badge/Status-experimental-7c3aed?style=flat-square"> <img alt="License MIT" src="https://img.shields.io/badge/Open%20Source-MIT-2563eb?style=flat-square"> </p>Why ROM
Most browser automation stacks start by shipping a full browser. ROM starts from the opposite direction:
- keep the runtime small and programmable
- emulate the browser surface incrementally
- validate compatibility against browser-facing probes and real harnesses
- stay transparent enough that the runtime can be inspected, extended, and reasoned about
The result is a native Rust workspace that aims to feel browser-like at the API layer without inheriting the operational weight of Chromium.
What ROM Is
- A Rust workspace with a lightweight embedded JavaScript engine.
- A growing browser API compatibility layer.
- A runtime designed around deterministic probes, snapshots, and acceptance harnesses.
- A Rust core with JS and Python bindings that can use either native extensions or the CLI bridge.
What ROM Is Not
- Not a full browser engine.
- Not a layout engine or Chromium replacement.
- Not production-complete yet.
- Not claiming full Web Platform coverage.
Highlights
| Area | Current State |
| --- | --- |
| Runtime core | Embedded JavaScript runtime lifecycle, script execution, error handling |
| Web platform | fetch, streams, blobs, files, URLs, parser, workers, messaging, cookies, SSE, WebSocket |
| Crypto | digest, HMAC, AES-CTR, AES-CBC, AES-GCM, AES-KW, PBKDF2, HKDF |
| Validation | Browser-like parameter validation, JWK validation, key usage validation, import/export edge handling |
| Compatibility | surface_snapshot(), fingerprint_probe(), vendored FingerprintJS harness, browser reference runner |
| Media and device surface | permissions, media devices, plugins, mime types, viewport, orientation, media queries |
Browser Surface Snapshot
Networking and data
fetchHeaders,Request,ResponseReadableStream-basedRequest.bodyandResponse.body- redirect modes:
follow,error,manual - CORS response gating and preflight validation
AbortController,AbortSignalBlob,File,FormDataURL,URLSearchParams,URLPatternDOMParserblob:object URLs- cookies via
document.cookie,Cookie, andSet-Cookie
Realtime and messaging
MessageEvent,MessagePort,MessageChannelBroadcastChannelWorkerwithBlobURL scripts,postMessage(), andimportScripts()EventSourcewithretry, reconnect, custom events,lastEventId, andclose()WebSocketwithws:andwss:, text and binary frames,Blobpayloads, and close events
Crypto
crypto.getRandomValues()crypto.randomUUID()crypto.subtle.digest()forSHA-1,SHA-256,SHA-384,SHA-512- HMAC
generateKey(),importKey(),exportKey(),sign(),verify() AES-CTR,AES-CBC,AES-GCMgenerateKey(),importKey(),exportKey(),encrypt(),decrypt()AES-GCM128/192/256-bit keys and tag lengths96..128AES-KWwrapping flowsPBKDF2andHKDFforimportKey(),deriveBits(),deriveKey()- browser-like secret-key validation for length, usages, params, JWK content, import/export, wrap/unwrap payloads, and derive semantics
DOM and compatibility surface
structuredClone()FileReadernavigator.permissions.query()navigator.mediaDevicesnavigator.userAgentDatanavigator.plugins,navigator.mimeTypes,navigator.pdfViewerEnabled- viewport globals,
visualViewport,screen.orientation,matchMedia() MutationObserver,ResizeObserver,IntersectionObserver- DOM event propagation with capture, bubble,
once, propagation stopping, andcomposedPath()
Architecture
<p align="center"> <img src="./assets/rom-compatibility-loop.svg" alt="ROM compatibility workflow" width="920" /> </p>The workspace is intentionally split into three layers:
crates/rom-coreRaw embedded JavaScript engine wrapper.crates/rom-webapiBrowser API bootstrap and compatibility shims.crates/rom-runtimeHigh-level environment assembly that composes engine and Web API behavior.
This separation keeps the core small, the web surface modular, and the runtime acceptance-focused.
Quick Start
Install the published bindings
npm install @rxflex/rom
pip install rom-runtime
Published packages:
- npm:
@rxflex/romhttps://www.npmjs.com/package/@rxflex/rom - PyPI:
rom-runtimehttps://pypi.org/project/rom-runtime/
If you want package-specific usage examples, see:
Runtime defaults
cors_enabledisfalseby default, so cross-originfetch()is direct by default instead of browser-blocked.proxy_urlis optional and supportshttp://,socks5://, andsocks5h://.cookie_storeis optional, but the Node.js and Python wrappers now update it automatically so cookies survive separate bridge-backed calls.- For convenience, the Node.js and Python wrappers also accept
cookie_storeas a raw cookie header string and acookiesalias with string/object/array inputs, then normalize it into ROM's serialized cookie store. local_storageandsession_storageare optional and accept serialized JSON objects, JS/Python maps, or entry arrays in the wrappers; updated values are synced back into wrapper config after each call.referreris optional if you needdocument.referrerto match an upstream page.- Native Node.js and Python bindings keep one live runtime per
RomRuntimeinstance, so globals, cookies, and storage created in oneeval()call remain available to the next call. - The default navigator surface is Chrome-like rather than ROM-branded, including
navigator.userAgent,navigator.vendor, andnavigator.userAgentData.
Build
cargo build
Run the full Rust test suite
cargo test
Use the CLI bridge directly
echo "{\"command\":\"surface-snapshot\"}" | cargo run -p rom-runtime --bin rom_bridge
Use the Node.js wrapper
import { RomRuntime, hasNativeBinding } from "@rxflex/rom";
const runtime = new RomRuntime({
href: "https://example.test/",
cors_enabled: false,
proxy_url: process.env.ROM_PROXY_URL ?? null,
});
const result = await runtime.evalAsync(`
(async () => {
document.cookie = "seed=1; path=/";
const response = await fetch("https://example.test/data");
return JSON.stringify({
href: location.href,
status: response.status,
body: await response.text(),
cookie: document.cookie,
});
})()
`);
console.log("native binding:", hasNativeBinding());
console.log(JSON.parse(result));
await runtime.evalAsync(`
(async () => {
await fetch("https://example.test/next");
return document.cookie;
})()
`);
console.log("persisted cookie store:", Boolean(runtime.config.cookie_store));
Optional native build:
cd bindings/gom-node
npm run build:native
Use the Python wrapper
from rom import RomRuntime, has_native_binding
runtime = RomRuntime(
{
"href": "https://example.test/",
"cors_enabled": False,
"proxy_url": None,
}
)
print("native binding:", has_native_binding())
result = runtime.eval_async(
"""
(async () => {
document.cookie = "seed=1; path=/";
const response = await fetch("https://example.test/data");
return JSON.stringify({
href: location.href,
status: response.status,
body: await response.text(),
cookie: document.cookie,
});
})()
"""
)
print(result)
runtime.eval_async(
"""
(async () => {
await fetch("https://example.test/next");
return document.cookie;
})()
"""
)
print("persisted cookie store:", bool(runtime.config.get("cookie_store")))
Optional native build:
python -m pip install maturin
python -m maturin develop --manifest-path bindings/gom-python/Cargo.toml
Run the browser reference harness
npm install
npx playwright install chromiu
