{"slug": "rustwright-a-rust-rewrite-of-playwright", "title": "Rustwright – a Rust Rewrite of Playwright", "summary": "Skyvern AI released Rustwright, a Rust rewrite of the Playwright browser automation library that is 2.55× faster and uses 70% less memory by eliminating the Node.js driver subprocess. The open-source tool supports Python and Node.js with a native Rust CDP engine, currently limited to Chromium, and is funded through Skyvern's paid Browser Sessions service.", "body_md": "**A Rust rewrite of Playwright**, a popular browser automation library. Rustwright is interoperable with Playwright but runs on an in-process Rust CDP engine — ** 2.55× faster** and\n\n**(no Node driver), with no Playwright automation fingerprint. Alpha; Chromium-only.**\n\n[70% less memory](/Skyvern-AI/rustwright/blob/main/BENCHMARK.md#client-memory-form-fill-diagnostic)Rustwright is a browser automation library for Python and Node.js that keeps the Playwright API you already know but drives Chromium from a **native Rust engine** speaking raw [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) — no driver subprocess in the path.\n\n```\nplaywright-python:  your code ──pipe──► Node driver ──CDP──► Chromium\nrustwright:         your code ────────── raw CDP ──────────► Chromium\n```\n\nRustwright is interoperable with Playwright — install it, change one import, and your existing code runs on the Rust engine.\n\n**Python**\n\n```\npip install rustwright\npython -m rustwright install chromium\npython\n- from playwright.sync_api import sync_playwright\n+ from rustwright.sync_api import sync_playwright\n\n  with sync_playwright() as p:\n      browser = p.chromium.launch(headless=True)\n      page = browser.new_page()\n      page.goto(\"https://example.com\")\n      print(page.title())\n      browser.close()\n```\n\n**Node.js** (experimental)\n\nInstall from npm:\n\n```\nnpm install rustwright\n```\n\nThe Node binding drives an existing Chromium/Chrome — point Rustwright at it with `RUSTWRIGHT_CHROMIUM`\n\n, `CHROME`\n\n, or `CHROMIUM`\n\n. Prefer to build from source? `git clone`\n\nthe repo and run `npm install && npm run build`\n\nin `node/`\n\n.\n\n``` js\n- import { chromium } from 'playwright';\n+ import { chromium } from 'rustwright';\n\n  const browser = await chromium.launch();\n  const page = await browser.newPage();\n  await page.goto('https://example.com');\n  console.log(await page.title());\n  await browser.close();\n```\n\nOnly a subset of the API surface is bridged — see [Limitations](#limitations).\n\n**No Node driver subprocess.**`playwright-python`\n\nlaunches and pipes to a bundled Node driver. Rustwright's engine is native — the browser-control code runs in-process.**Raw CDP, in Rust.** A from-scratch async CDP client — not a wrapper around another automation library.**No Playwright automation fingerprint.** The driver never loads, so its signatures never appear. See[Automation detection](#automation-detection).**Trusted input by default.** Clicks and typing go through real CDP input events (`Input.dispatchMouseEvent`\n\n), not synthetic`element.click()`\n\nDOM calls. Untrusted DOM shortcuts are opt-in only.**Cross-origin iframes (OOPIF).** Auto-attaches out-of-process iframe targets with flattened CDP sessions and routes`frame_locator()`\n\nacross origins.**One engine, two languages.** The same Rust core backs the Python and Node bindings.\n\nOne Rust core — an async CDP client built on Tokio (WebSocket, with opt-in Unix-pipe transport) — talks to Chromium directly, and thin [PyO3](https://pyo3.rs) (Python) and [napi-rs](https://napi.rs) (Node) bindings expose it in-process. The two-line diagram above is the entire architecture.\n\nAlready have a Chromium/Chrome binary? Point Rustwright at it with `RUSTWRIGHT_CHROMIUM`\n\n, `CHROME`\n\n, or `CHROMIUM`\n\n.\n\nRustwright drives browsers — but you still need somewhere to run them. Skyvern (the team behind Rustwright) offers hosted ** Browser Sessions** as a paid service that funds this project.\n\n**Features:**\n\n**Persistent cloud browsers**— logins, cookies, and tab state carry across runs** Configurable timeouts**— 5 minutes to 24 hours (60 min default)** Proxies in 21 countries****Live view**— watch and interact with the session in the Skyvern Cloud UI\n\nEach session returns a `browser_address`\n\nCDP endpoint that Rustwright connects to like any remote Chromium (sessions bill while open).\n\n**Get started:**\n\n- Make an account at\n[app.skyvern.com](https://app.skyvern.com) - Grab your API key from\n**Settings** `pip install skyvern`\n\n``` python\nimport asyncio\nfrom rustwright.async_api import async_playwright\nfrom skyvern import Skyvern\n\nasync def main():\n    session = await Skyvern(api_key=\"<SKYVERN_API_KEY>\").create_browser_session()\n\n    async with async_playwright() as p:\n        browser = await p.chromium.connect_over_cdp(session.browser_address)\n        page = await browser.new_page()\n        await page.goto(\"https://example.com\")\n\nasyncio.run(main())\n```\n\nRemote sessions are Python-only for now — Rustwright's Node binding doesn't support\n\n`connect_over_cdp`\n\nyet (it's on the[Roadmap]).\n\nBecause Rustwright never loads Playwright's Node driver, it never emits the automation signatures that ship with it:\n\n**No Playwright driver signatures**— no`__playwright__binding__`\n\n/ utility-world globals, no driver bootstrap. The backend reports`playwright_driver: \"none\"`\n\n.**No**— a normal launch + navigate never enables the CDP Runtime domain, closing the`Runtime.enable`\n\non the default path`Runtime.enable`\n\nconsole-serialization leak behind`isAutomatedWithCDP`\n\n. (Console/page-error/binding opt-ins still enable it lazily — detectable by design.)**Headless identity normalized by default**— launches with`--disable-blink-features=AutomationControlled`\n\n, rewrites`HeadlessChrome/`\n\n→`Chrome/`\n\nin the UA and client hints, and installs a`navigator.webdriver`\n\ncleanup init script.\n\nLocal fingerprint runs — default Playwright failed webdriver/headless checks that Rustwright passed; these are local diagnostics, not a guarantee:\n\n| Probe | Result |\n|---|---|\n| SannySoft | ✅ Clean |\n| BrowserScan | ✅ Clean |\n| DeviceAndBrowserInfo | ✅ Clean (after the Runtime-domain cleanup) |\n| CreepJS |\n\nImportant\n\n**Rustwright is not \"undetectable.\"** It is not a CAPTCHA or Cloudflare bypass, and it is not fully CDP-invisible — it still uses CDP primitives (`Target.setAutoAttach`\n\n, init scripts, and lazy `Runtime.enable`\n\nfor console event/pageerror event/binding opt-ins). The claim is narrow: **no Playwright-specific automation fingerprint**, plus baseline signal hygiene.\n\nThe headline numbers are local diagnostics, not yet capped-CI evidence. On speed, one dev-host run (warm browser, 5 iterations) won 16 of 17 case means:\n\n| Run | Cases | Rustwright | playwright-python | Speedup |\n|---|---|---|---|---|\n| Local dev host (warm browser, 5 iterations) | 17 | 5,256 ms | 13,418 ms |\n|\n\nTreat it as a diagnostic, not a launch claim — it is not capped-Docker/CI evidence. Methodology: [ BENCHMARK.md](/Skyvern-AI/rustwright/blob/main/BENCHMARK.md).\n\nOn memory, a [form-fill diagnostic](/Skyvern-AI/rustwright/blob/main/BENCHMARK.md#client-memory-form-fill-diagnostic) recorded the client library's footprint at **133.5 MiB for playwright-python (Python + Node driver) versus 40.6 MiB for Rustwright (no driver) — about 70% less**; a separate [async-concurrency diagnostic](/Skyvern-AI/rustwright/blob/main/docs/async-design.md#update-high-concurrency-fixes-2026-07) measured ~66% less on the same client-stack basis. Both cover the part the library controls — Chromium-dominated whole-process memory is roughly equal — and both are demo-grade diagnostics, not capped-CI evidence.\n\n| Rustwright | playwright-python | Puppeteer | Patchright | |\n|---|---|---|---|---|\nAPI |\nPlaywright-shaped (Py + Node) | Official Python Playwright | JS/TS Puppeteer | Playwright drop-in fork |\nEngine / transport |\nRust core, raw CDP | Python → Node driver | Node over CDP | Patched PW driver |\nIn-process engine (no driver subprocess) |\n✅ | ❌ bundled Node driver | ✅ Node is the runtime | ❌ Playwright-style driver |\nBrowsers |\nChromium only | Chromium, Firefox, WebKit | Chrome, Firefox | Chromium-based |\nDefault input |\nTrusted CDP events | Browser-level | Browser / CDP | Playwright + stealth |\nCross-origin iframes |\nOOPIF (alpha) | Mature | Frame APIs | Inherits Playwright |\nPlaywright fingerprint |\nNo | Yes | n/a | Patched |\nMaturity |\n🟠 Alpha | 🟢 Mature | 🟢 Mature | 🟡 Focused fork |\n\nRustwright's lane: **a Rust CDP engine under the Playwright API, for Chromium.**\n\nSee [ LIMITATIONS.md](/Skyvern-AI/rustwright/blob/main/LIMITATIONS.md) for detail.\n\n**Alpha**— API shape covered; full** behavioral**parity not yet proven.** API coverage**— ~96% of Playwright's Python sync API (** 515 of 536**methods;** 411**exercised by the shared parity registry); the async API provides** 488 of 536**. Full report:.`docs/PARITY.md`\n\n**Chromium only**— Firefox and WebKit error explicitly.** Node bindings are early**— a subset of the surface is bridged (`launch`\n\n,`newPage`\n\n,`goto`\n\n,`click`\n\n,`fill`\n\n,`title`\n\n,`textContent`\n\n,`evaluate`\n\n,`screenshot`\n\n,`close`\n\n); contexts, routing, tracing, and locators are Python-only for now.**Async concurrency (Python)**— the async API wraps the sync engine via threads; recommended for**≈≤25 concurrent workflows/process**, not high fan-out.** OOPIF**— residual gaps in non-main-frame`JSHandle`\n\nfollow-ups and drag/screenshot/bounding-box.**Automation detection is partial**— 3 of 4 public fingerprint targets clean in local runs (CreepJS still detects headless).** No undetectability promise.**\n\n-\n**Language bindings**— one Rust engine, many languages: Go, Java, Kotlin, C#/.NET, Ruby, and PHP (plus a native Rust API) -\n**Rustwright MCP server**— expose browser automation as tools for MCP-compatible AI agents - CI / Testbox-backed benchmark evidence\n- Broaden the Node.js surface (contexts, routing, locators)\n- Close remaining OOPIF gaps\n\nRecently shipped:\n\n- Python package published to PyPI\n- Node.js binding published to npm\n- Native async engine over the Tokio CDP core\n- OOPIF auto-attach with flattened CDP sessions\n- 515/515 shared parity suite green against real Playwright\n-\n`Runtime.enable`\n\nconsole-serialization leak closed on the default path\n\nFirefox and WebKit are **not planned** — Rustwright is deliberately Chromium-only.\n\nRustwright is Rust + Python + Node. `cargo`\n\nbuilds the engine; `maturin develop --release`\n\ninstalls the Python package; `cd node && npm run build`\n\nbuilds the Node addon; the Python suite exercises the engine against real Chromium. Full Docker gate: **1,046 tests pass** (6 skipped), plus **515/515** shared parity cases run against real Playwright; CI (`test.yml`\n\n) runs a fast representative subset on every PR.\n\nSee [ CONTRIBUTING.md](/Skyvern-AI/rustwright/blob/main/CONTRIBUTING.md) for build details and the code-layout reality.\n\nRustwright is an early alpha from [Skyvern](https://github.com/Skyvern-AI), developed in the open. If the architecture resonates, [give it a ⭐](https://github.com/Skyvern-AI/rustwright).\n\nQuestions, ideas, or want to help? Join the Skyvern community on [ Discord](https://discord.gg/fG2XXEuQX3).\n\n[MIT](/Skyvern-AI/rustwright/blob/main/LICENSE) © 2026 Ikonomos Inc (dba Skyvern)\n\nBuilt with 🦀🐉 and a lot of CDP frames ·", "url": "https://wpnews.pro/news/rustwright-a-rust-rewrite-of-playwright", "canonical_source": "https://github.com/Skyvern-AI/rustwright", "published_at": "2026-07-16 09:29:36+00:00", "updated_at": "2026-07-16 09:55:49.343120+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence"], "entities": ["Skyvern AI", "Rustwright", "Playwright", "Chromium", "Chrome DevTools Protocol", "Tokio", "PyO3", "napi-rs"], "alternates": {"html": "https://wpnews.pro/news/rustwright-a-rust-rewrite-of-playwright", "markdown": "https://wpnews.pro/news/rustwright-a-rust-rewrite-of-playwright.md", "text": "https://wpnews.pro/news/rustwright-a-rust-rewrite-of-playwright.txt", "jsonld": "https://wpnews.pro/news/rustwright-a-rust-rewrite-of-playwright.jsonld"}}