Robust browser session management for Playwright & Browser.cash.
Powered by Browser.cash remote browsers.
Features • Installation • Usage • Configuration • Contributing
💡 Pro Tip: See this library in action in Teracrawl and Browser SERP.
Browser Pool is a specialized library designed to manage pools of remote browser sessions. It handles the lifecycle of Playwright browsers connected to Browser.cash, ensuring your application always has a healthy browser ready to perform tasks.
It abstracts away the complexity of connection management, error recovery, and session recycling, making it ideal for building high-concurrency scrapers and automation tools.
- Automatic Pooling: Maintains a fixed number of active browser sessions.
- Target-Aware Pooling: Specify exactly how many browsers you want per node, country, or node type.
- Self-Healing: Automatically detects and replaces dead or disconnected browsers.
- Health Checks: Periodically verifies browser responsiveness.
- Concurrency Control: Queues requests when all sessions are busy.
- Type-Safe: Written in TypeScript with full type definitions.
npm install @browsercash/poolNote: You must also have playwright-core installed as a peer dependency.
import{chromium}from"playwright-core";import{SessionPool,typePoolConfig}from"@browsercash/pool";constcfg: PoolConfig={apiKey: process.env.BROWSER_API_KEY,
chromium,targets: [{id: "us-hosted",count: 2,country: "US",type: "hosted"},{id: "de-consumer",count: 1,country: "DE",type: "consumer_distributed"},{id: "pinned-node",count: 1,nodeId: "node_123"},],enableHealthCheck: true,waitQueueTimeoutMs: 30_000,};// 1. Create the poolconstpool=newSessionPool(cfg);// 2. Initializeawaitpool.init();// 3. Acquire a session (waits if none available)constsession=awaitpool.acquire();try{// Use the standard Playwright browser instanceconstpage=awaitsession.browser.newPage();awaitpage.goto("https://example.com");console.log(awaitpage.title());}finally{// 4. Always release the session back to the pool// Pass 'true' as second arg if the session encountered a fatal errorpool.release(session);}// 5. Cleanup on shutdownawaitpool.shutdown();There is also a dedicated example config file in
examples/browser-pool.config.mjs.
If you just want the old behavior, size still works:
constpool=newSessionPool({apiKey: process.env.BROWSER_API_KEY,
chromium,size: 3,});import{chromium}from"playwright-core";import{typePoolConfig}from"@browsercash/pool";exportconstbrowserPoolCfg: PoolConfig={apiKey: process.env.BROWSER_API_KEY!,
chromium,targets: [{id: "us-primary",count: 2,country: "US",type: "hosted"},{id: "eu-fallback",count: 2,country: "DE",type: "consumer_distributed"},{id: "pinned-fraud-node",count: 1,nodeId: "node_123"},],maxUses: 25,maxAgeMs: 10*60*1000,maxIdleMs: null,enableHealthCheck: true,healthCheckIntervalMs: 30_000,sessionReadyTimeoutMs: 30_000,cdpConnectTimeoutMs: 15_000,waitQueueTimeoutMs: 60_000,};Equivalent standalone file:
// examples/browser-pool.config.mjsimport{chromium}from"playwright-core";exportconstbrowserPoolCfg={apiKey: process.env.BROWSER_API_KEY,
chromium,targets: [{id: "de-consumer",count: 1,country: "DE",type: "consumer_distributed"},],maxUses: 25,maxAgeMs: 10*60*1000,maxIdleMs: null,enableHealthCheck: true,healthCheckIntervalMs: 30_000,sessionReadyTimeoutMs: 30_000,cdpConnectTimeoutMs: 15_000,waitQueueTimeoutMs: 60_000,};For a larger production mix, expand targets with more entries such as hosted US nodes or pinned nodeId targets.
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | Required | Your Browser.cash API key. |
chromium | ChromiumModule | Required | The Playwright Chromium module. |
size | number | 1 | Backward-compatible shortcut for a single default target group. |
targets | PoolTarget[] | [] | Explicit target mix. Sum of count values becomes the pool size. |
maxUses | number | 50 | Max times a browser is reused before recycling. |
maxAgeMs | number | 300000 | Max age (ms) of a session before recycling. |
maxIdleMs | number | null | null | Max idle time before recycling. null or 0 disables idle recycling. |
enableHealthCheck | boolean | false | Enable background remote health checks. |
healthCheckIntervalMs | number | 30000 | Interval for health checks (ms). |
healthCheckTimeoutMs | number | min(interval, 10000) | Timeout for each health-check request. |
sessionReadyTimeoutMs | number | 20000 | How long to wait for Browser.cash to return a usable CDP URL. |
cdpConnectTimeoutMs | number | 15000 | Timeout for Playwright connectOverCDP. |
enableWaitQueue | boolean | true | Queue acquire requests if pool is full. |
waitQueueTimeoutMs | number | 60000 | Max time an acquire call will wait in queue. |
enableDisconnectHandling | boolean | true | Replace sessions when the CDP connection disconnects. |
createPage | boolean | false | Pre-create a page for each pooled session. |
debug | boolean | false | Enable verbose logging. |
logger | (message, data) => void | console.log | Custom logger used when debug is enabled. |
typePoolTarget={id?: string;count: number;nodeId?: string;country?: string;type?: "consumer_distributed"|"hosted";sessionOptions?: Record<string,unknown>;};- Use
countto pin how many sessions should exist for that target. - Use
nodeIdwhen you want a specific Browser.cash node. - Use
countryandtypewhen you want the pool to maintain a regional mix. - Use
sessionOptionsas a pass-through for newer Browser.cash session-create fields.
Contributions are welcome! We appreciate your help in making Browser Pool better.
- Fork the Project: click the 'Fork' button at the top right of this page.
- Create your Feature Branch:
git checkout -b feature/AmazingFeature - Commit your Changes:
git commit -m 'Add some AmazingFeature' - Push to the Branch:
git push origin feature/AmazingFeature - Open a Pull Request: Submit your changes for review.
This project is licensed under the MIT License - see the LICENSE file for details.