Playwright cloud
Run Playwright on hosted Chromium
One API call returns a CDP URL. Pass it to chromium.connectOverCDP() and your existing Playwright code runs against a real headed Chrome in the cloud.
No SDK to add to package.json. No fixture rewrites. The only line that changes is the connection URL.
Free tier · $0.15/hour after · No credit card
Connect in 6 lines
import { chromium } from "playwright";
const res = await fetch("https://browsers.bug0.com/api/v1/sessions", {
method: "POST",
headers: { Authorization: "Bearer bug0_sk_YOUR_KEY" },
});
const { cdpUrl } = await res.json();
const browser = await chromium.connectOverCDP(cdpUrl);
const page = browser.contexts()[0].pages()[0];
await page.goto("https://example.com");
console.log(await page.title());
await browser.close();That's the whole API. Create session, get URL, connectOverCDP, drive the page. When you're done, stop the session so it stops billing.
Drop-in for @playwright/test
Most teams want this in their test suite, not a one-off script. Use a Playwright fixture that creates a Bug0 session per worker.
import { test as base } from "@playwright/test";
import { Bug0 } from "@bug0/sdk";
const bug0 = new Bug0({ apiKey: process.env.BUG0_API_KEY! });
export const test = base.extend<{ cdpUrl: string }>({
cdpUrl: async ({}, use) => {
const session = await bug0.createBrowser();
await use(session.cdpUrl);
await bug0.stopBrowser(session.sessionId);
},
});Pass cdpUrl to chromium.connectOverCDPin the test, or use Playwright's connectOptions to point the whole project at it.
Real headed Chrome, every test
Bug0 runs unmodified Chromium on a virtual display. Headed, not headless. That matters for tests that depend on the things headless mode quietly skips: fonts, video codecs, the actual rendering pipeline. If a flake only repros for one team member on macOS Chrome, it'll repro here too.
Real Chrome
Not Chromium-headless. Same binary your users run.
Virtual display
Headed mode. Fonts, video, GPU paths behave like a desktop.
Live preview
noVNC stream of every session. Useful when CI fails and you can't reproduce locally.
What it costs vs running Chrome in CI
A typical PR test run is 5 to 10 minutes of browser time per job. At $0.15/hr that's $0.0125 to $0.025 per run. A team running 200 PRs a month spends $2.50 to $5. Cheaper than a single hour of someone debugging "works on my machine" against a CI runner with a missing font.
Pricing
$0.15 per hour, billed per minute. 10 free browser-minutes at sign-up. No monthly minimum. Stop the session, stop the meter.
Frequently asked questions
What is Playwright cloud?
Playwright cloud means running Playwright scripts against a remote browser instead of one you launched locally. Bug0 gives you a CDP URL that chromium.connectOverCDP() plugs into. Your existing tests run unchanged.
Which Playwright versions are supported?
Anything that speaks CDP. That covers every modern Playwright release. Both @playwright/test and the standalone playwright package work.
Can I run tests in parallel?
Yes. Each Bug0 session is its own browser. A Playwright project with 10 workers creates 10 sessions, each billed independently. The fixture pattern above handles the lifecycle.
What about authentication state?
Use Playwright's storageState as you would locally. Store the JSON in your secrets manager and load it on browser context creation. Bug0 doesn't manage cookies or auth for you, intentionally.
Can I use it from GitHub Actions?
Yes. Set BUG0_API_KEY as a secret, run npx playwright test in your workflow, and the fixture above handles the rest. No browser install step needed because the browser isn't local.
Headed or headless?
Headed. Bug0 runs Chromium with a real display, which catches a class of bugs that --headless quietly hides.
Is there a free tier?
10 browser-minutes free, no credit card. Enough to wire up a fixture and run your suite a few times.