I built a self-hosted browser pool for short-lived Playwright tasks
Hi everyone! I built BrowserThing, an open-source, self-hosted browser pool for applications using Playwright. I originally built it for a workload with lots of short browser tasks. Starting a fresh browser process for every task felt wasteful, but keeping the same browser alive indefinitely wasn't ideal either - long-running browsers can grow in memory usage and eventually end up in a bad state. BrowserThing takes a middle approach: it keeps browsers warm and reuses them across tasks, while monitoring and periodically recycling them after a configurable amount of work. For a short workload - connect, open a page, read it, disconnect - I measured: Task time CPU time / task BrowserThing 51 ms 0.09 s Browserless 217 ms 0.70 s That’s about 87% less CPU time per task in this particular workload. This isn't meant as a general BrowserThing vs Browserless performance comparison - it's specifically a case where browser startup overhead matters. From the application side, you connect Playwright to a single WebSocket endpoint: const browser = await chromium.connect('ws://your-browserthing-host:8080'); This is standard Playwright - you can connect from any Playwright-supported language, and the rest of your code stays the same. At a high level, it: Reuses warm browsers across tasks Monitors and recycles browser processes Load balances work across multiple workers or machines One important tradeoff: sessions can share browser processes, so you don't get a separate browser process for every client. Cookies and storage are still isolated through Playwright browser contexts, so it's mainly intended for your own applications and trusted clients. It's Apache-2.0 licensed, with a Docker Compose quick start in the README. GitHub: github.com/mbroton/browserthing