BLOG
Browserless Alternative GitHub: What to Run Instead
Compare Browserless alternatives on GitHub, from self-hosted projects to hosted CDP runtimes, and learn how to wire Playwright into production agents.
# Browserless Alternative GitHub: What to Run Instead
If you searched for a browserless alternative github, you are probably in one of two situations. Either you self-host Browserless and the operational load has outgrown the value, or you want to see the source before you commit to a hosted browser runtime. Both are reasonable. This post covers what actually exists on GitHub, what the trade-offs are, and how to connect a hosted Chromium runtime to Playwright, Puppeteer, or Selenium over CDP when self-hosting stops making sense.
The short version: Browserless is a solid open-source project, but "open source" and "zero ops" are different promises. Most teams that leave Browserless do not leave because the code is bad. They leave because running browsers at scale means owning container orchestration, memory limits, zombie Chrome processes, session cleanup, outbound IP management, and a queue that does not fall over at 3 a.m.
What Browserless actually gives you
Browserless is a Node-based service that wraps headless Chrome behind HTTP and WebSocket endpoints. You POST to /content, /pdf, /screenshot, or open a WebSocket to /chromium and drive it with Puppeteer or Playwright. It handles browser pooling, session limits, and some concurrency control so you do not spawn a Chrome per request.
That is genuinely useful. The GitHub repo is active, the Docker image is straightforward, and for a single-node workload it works well.
The friction shows up when you scale:
- Memory is the bottleneck. Each Chromium context costs a meaningful amount of RAM. A 4 GB container handles a handful of concurrent sessions before the OOM killer arrives.
- You own the queue. Browserless does not give you a distributed job queue. You build that, or you accept dropped requests under load.
- You own the outbound network. Residential and mobile proxy configuration, sticky sessions, and per-session IP assignment are your problem.
- You own the upgrades. Chrome ships every few weeks. So does the CDP surface. So does Browserless.
- You own the debugging. When a session hangs, you SSH in and read logs. There is no live viewer unless you build one.
None of this is a knock on the project. It is the honest cost of self-hosting a stateful, memory-hungry service.
Open-source alternatives on GitHub
If you want to stay fully self-hosted, these are the projects people actually evaluate.
| Project | Model | Protocol | Best for | Main trade-off |
|---|---|---|---|---|
| Browserless | Self-hosted service | CDP, HTTP | Simple screenshot/PDF APIs | You run the infra |
| Playwright | Library | CDP, native | Test suites, scripting | No server, no pooling |
| Puppeteer | Library | CDP | Chrome-only automation | No server, no pooling |
| Selenium Grid | Self-hosted grid | WebDriver | Cross-browser matrix | Heavy, slow to start |
| Steel Browser | Open-source browser API | CDP | Open-source hosted-style API | Still self-hosted |
| browser-use | Agent framework | CDP | LLM-driven agents | Runtime is your concern |
The pattern is consistent: the libraries (Playwright, Puppeteer) are excellent and you should use them. The *runtime* — the thing that keeps browsers alive, isolated, and reachable — is where self-hosting gets expensive.
If your workload is a nightly test suite on one machine, Playwright alone is the right answer. If your workload is many concurrent agent sessions with persistent profiles and proxy requirements, you are building a browser platform whether you meant to or not.
Where hosted runtimes fit
A hosted browser runtime is the same idea as Browserless, minus the part where you operate it. You get a CDP WebSocket endpoint, you connect Playwright or Puppeteer to it, and the provider handles pooling, isolation, cleanup, and scaling.
Remote Browser is one of these. It provides hosted Chromium sessions with CDP access, Playwright/Puppeteer/Selenium compatibility, a live viewer for debugging, persistent profiles, configurable browser and proxy settings, and session isolation. You can read the documentation for the connection details and check pricing for current rates rather than relying on numbers in a blog post.
The relevant question is not "open source or not." It is "which parts of this stack do I want to own."
Connecting to a hosted runtime over CDP
This is the part that matters. If a runtime speaks CDP, your existing Playwright code works with a one-line change. Here is a TypeScript example that connects to a remote Chromium endpoint, creates a context, and runs a task:
import { chromium, Browser, BrowserContext, Page } from 'playwright';
const CDP_ENDPOINT = process.env.REMOTE_BROWSER_CDP_URL!;
async function runTask(): Promise<void> {
// connectOverCDP attaches to an already-running browser.
// No local Chrome download, no launch flags to tune.
const browser: Browser = await chromium.connectOverCDP(CDP_ENDPOINT, {
timeout: 30_000,
});
// Reuse the default context or create an isolated one.
const context: BrowserContext = await browser.newContext({
viewport: { width: 1440, height: 900 },
locale: 'en-US',
});
const page: Page = await context.newPage();
try {
await page.goto('https://example.com', {
waitUntil: 'domcontentloaded',
timeout: 45_000,
});
const title = await page.title();
console.log('loaded:', title);
// Your agent or automation logic goes here.
await page.getByRole('link', { name: /docs/i }).first().click();
await page.waitForLoadState('networkidle');
} finally {
// Close the context, not the browser, when the runtime owns the browser.
await context.close();
await browser.close();
}
}
runTask().catch((err) => {
console.error('task failed:', err);
process.exit(1);
});Two details that trip people up:
- `connectOverCDP` is Chromium-only. Firefox and WebKit do not expose a CDP endpoint. If you need cross-browser, use a WebDriver-based grid or Playwright's own remote server model.
- Do not call `browser.close()` if you intend to reuse the session. With a hosted runtime, closing the browser tears down the session. Close the context and let the runtime recycle.
The Playwright team documents the connection semantics in the BrowserType.connectOverCDP reference, and the underlying protocol is specified in the Chrome DevTools Protocol docs. Both are worth reading before you build retry logic.
Production criteria for choosing a runtime
When you compare Browserless, a self-hosted alternative, and a hosted runtime, evaluate against these criteria rather than feature lists.
Session isolation. Can two concurrent sessions share cookies, localStorage, or an outbound IP? They should not, unless you explicitly want that. Isolation is the difference between a clean run and a cross-contaminated one.
Persistent profiles. Agents that log in once and return need a profile that survives across sessions. Ask how profiles are stored, how long they persist, and whether you can pin a session to a profile.
Proxy and network control. Per-session proxy assignment, sticky sessions, and geographic targeting matter for anything touching protected sites. "Configurable browser settings" is the honest description of what most runtimes offer; verify specifics before assuming behavior.
Live debugging. When an agent fails at step 14 of 20, you want to see the DOM, the console, and the network tab. A live viewer saves hours. Remote Browser exposes one; see Remote Browser Online for how that works in practice.
Concurrency and metering. Know whether you are billed per browser-hour, per session, or per request, and whether idle sessions count. Check pricing for the current model instead of trusting a comparison table written six months ago.
Protocol compatibility. CDP is the lingua franca. If a runtime speaks CDP, you can use Playwright, Puppeteer, or raw WebSocket clients. If it only speaks a proprietary HTTP API, you are locked into their SDK.
Browserless vs hosted runtime: the honest comparison
| Dimension | Self-hosted Browserless | Hosted runtime (e.g. Remote Browser) |
|---|---|---|
| Setup time | Hours to days | Minutes |
| Infra ownership | You | Provider |
| Scaling | Manual, capacity-planned | Provider-managed |
| Debugging | SSH + logs | Live viewer + CDP |
| Cost model | Your compute + your time | Metered usage |
| Customization | Full source access | Configurable settings |
| Vendor risk | None | Provider dependency |
| Best fit | Tight control, existing infra | Teams shipping agents |
The "cost" row is where people get surprised. Self-hosted Browserless is cheap on paper and expensive in engineering hours. A hosted runtime is the reverse. If your team has a platform engineer with spare cycles, self-hosting is defensible. If your team is three people shipping an agent product, it usually is not.
When to stay on GitHub and when to move
Stay self-hosted if:
- You have strict data residency or air-gapped requirements.
- Your concurrency is low and predictable.
- You already run Kubernetes and browser containers are just another workload.
- You need to patch Chromium itself.
Move to a hosted runtime if:
- Your agent workload is bursty and you do not want to over-provision.
- You need persistent profiles and proxy control without building it.
- You want a live viewer for debugging instead of log spelunking.
- Your time is better spent on the agent than on the browser.
For a deeper look at how hosted Chromium changes agent reliability, see Remote Browser for AI Agents. For the mechanics of driving a remote session from code, Remote Control Browser walks through the control path.
A migration path that does not break things
You do not have to rip out Browserless to evaluate a hosted runtime. Run both.
- Abstract the connection. Put your CDP endpoint behind an environment variable. Your code should not care whether it points at
ws://localhost:3000or a hosted URL. - Shadow a percentage of traffic. Route 5% of sessions to the hosted runtime. Compare success rates, latency, and failure modes.
- Move the hard cases first. Protected sites, login flows, and long-running agent tasks benefit most from managed profiles and proxies.
- Keep the fallback. Until you are confident, keep the self-hosted path available. A runtime is infrastructure; treat the cutover like any other.
The abstraction is the important part. If your Playwright code hardcodes a local endpoint, every runtime decision becomes a refactor.
Bottom line
Browserless is a good project and a reasonable starting point. The question is whether you want to operate a browser platform or use one. GitHub gives you the source; it does not give you the on-call rotation, the capacity planning, or the live debugging UI.
If you want the CDP endpoint without the ops, start with the documentation, connect Playwright with connectOverCDP, and see how your existing scripts behave. Most teams find the migration is a connection string, not a rewrite.