|
| 1 | +--- |
| 2 | +permalink: /alternative-browsers |
| 3 | +title: Alternative Browser Engines |
| 4 | +--- |
| 5 | + |
| 6 | +# Alternative Browser Engines |
| 7 | + |
| 8 | +Playwright and Puppeteer drive full Chromium — the most accurate way to test what users see. |
| 9 | +But a new class of lightweight, agent-era browsers has appeared, and CodeceptJS can drive them |
| 10 | +through the `CDPBrowser` helper family: |
| 11 | + |
| 12 | +- **[Obscura](https://github.com/h4ckf0r0day/obscura)** — an open-source Rust browser with a real |
| 13 | + V8 engine but no rendering. A single 70 MB binary, ~30 MB RAM per instance, page loads in |
| 14 | + tens of milliseconds. |
| 15 | +- **[Kitesurf](https://blog.cloudflare.com/kitesurf/)** — Cloudflare's browser that runs in V8 |
| 16 | + isolates on Cloudflare Workers, with a real layout and rendering pipeline. Cloud-only, |
| 17 | + free in beta, planned to be open-sourced. |
| 18 | + |
| 19 | +Both speak Chrome DevTools Protocol. CodeceptJS drives them with raw CDP — one round-trip per |
| 20 | +action, no stale element handles — which is why suites on these browsers run fast and never hang |
| 21 | +on navigation races. |
| 22 | + |
| 23 | +## When are they better than Playwright? |
| 24 | + |
| 25 | +**Smoke suites where seconds matter.** An Obscura scenario (navigate, fill a form, submit, |
| 26 | +assert) completes in 150–500 ms. There is no browser binary to download in CI — a 70 MB |
| 27 | +static binary starts instantly. If your PR gate runs 50 smoke scenarios, Obscura turns |
| 28 | +minutes into seconds. |
| 29 | + |
| 30 | +**Massive parallel scale.** Kitesurf sessions are Cloudflare Workers — they spawn in about a |
| 31 | +second, cost nothing while idle, and there is no practical ceiling on how many you run at once. |
| 32 | +Combined with `run-workers`, every worker acquires its own cloud browser: |
| 33 | + |
| 34 | + // codecept.conf.js — each worker independently loads the config, |
| 35 | + // so each one gets its own Kitesurf session automatically |
| 36 | + export const config = { |
| 37 | + helpers: { |
| 38 | + Kitesurf: { |
| 39 | + url: 'https://staging.myapp.com', |
| 40 | + }, |
| 41 | + }, |
| 42 | + } |
| 43 | + |
| 44 | + npx codeceptjs run-workers 16 |
| 45 | + |
| 46 | +Sixteen cloud browsers, zero local resources, feedback in the time of your slowest test. |
| 47 | +Scale the number up as far as your suite can split — the browsers are no longer |
| 48 | +the bottleneck, and your CI runner only coordinates. |
| 49 | + |
| 50 | +**Testing the DOM, not the pixels.** Most functional assertions — text appears, form submits, |
| 51 | +redirect happens, cookie is set — do not need a GPU raster pipeline. Obscura executes your |
| 52 | +app's real JavaScript in real V8; it only skips painting. For API-adjacent flows |
| 53 | +(login → dashboard data appears), that is exactly the right amount of browser. |
| 54 | + |
| 55 | +**Constrained environments.** ARM CI runners, thin containers, air-gapped machines: |
| 56 | +a static binary with no system dependencies goes where Chromium will not. |
| 57 | + |
| 58 | +**Scraping-grade network realism.** Obscura's stealth mode presents a consistent Chrome TLS |
| 59 | +fingerprint — useful when your tests must pass through bot-protection layers that block |
| 60 | +headless Chromium. |
| 61 | + |
| 62 | +## When to stay with Playwright |
| 63 | + |
| 64 | +- Anything visual: screenshots, visual regression, PDF (Obscura cannot; Kitesurf can). |
| 65 | +- Visibility semantics: on Obscura every element reports as visible — `seeElement`/`dontSeeElement` |
| 66 | + throw and point you to `seeElementInDOM`. |
| 67 | +- Complex input: drag-and-drop, hover chains, file uploads, iframes, multi-tab, service workers. |
| 68 | +- Cross-browser coverage (Firefox, WebKit). |
| 69 | +- Testing local apps with Kitesurf: the cloud browser must reach your app; use a tunnel |
| 70 | + (`cloudflared tunnel --url http://localhost:3000`) or a deployed environment. |
| 71 | + |
| 72 | +## Configuration |
| 73 | + |
| 74 | + helpers: { |
| 75 | + Obscura: { |
| 76 | + url: 'http://localhost:3000', |
| 77 | + binaryPath: '/usr/local/bin/obscura', |
| 78 | + }, |
| 79 | + } |
| 80 | + |
| 81 | + helpers: { |
| 82 | + Kitesurf: { |
| 83 | + url: 'https://staging.myapp.com', |
| 84 | + accountId: process.env.CF_ACCOUNT_ID, |
| 85 | + apiToken: process.env.CF_API_TOKEN, |
| 86 | + }, |
| 87 | + } |
| 88 | + |
| 89 | +Any other CDP endpoint works through the base helper: |
| 90 | + |
| 91 | + helpers: { |
| 92 | + CDPBrowser: { |
| 93 | + url: 'http://localhost:3000', |
| 94 | + endpoint: 'http://127.0.0.1:9222', |
| 95 | + }, |
| 96 | + } |
| 97 | + |
| 98 | +## Capability matrix |
| 99 | + |
| 100 | +| | Playwright | Obscura | Kitesurf | |
| 101 | +|---|---|---|---| |
| 102 | +| Real JS execution (V8) | yes | yes | yes | |
| 103 | +| Layout / getBoundingClientRect | yes | synthetic | yes | |
| 104 | +| Screenshots | yes | no | yes | |
| 105 | +| Visibility assertions | yes | no (DOM-presence only) | yes | |
| 106 | +| Startup cost | seconds + ~300 MB install | instant, 70 MB binary | ~1 s, zero local | |
| 107 | +| Parallel scale | machine-bound | machine-bound (light) | near-unlimited (cloud) | |
| 108 | +| Where it runs | local/grid | local | Cloudflare only | |
| 109 | +| License / cost | open source | Apache-2.0 | proprietary, free beta | |
| 110 | + |
| 111 | +See helper reference pages: [CDPBrowser](/helpers/CDPBrowser), [Obscura](/helpers/Obscura), |
| 112 | +[Kitesurf](/helpers/Kitesurf). |
0 commit comments