How browser pools work
1
Declare a browser pool
Create a browser pool with your configuration and a fixed size. It takes a few minutes to fill, so declare it at deploy time or on startup rather than in the path that serves your workload.
2
Acquire a browser
acquire returns a ready browser immediately, or waits until one frees up. A browser pool holds a fixed number of browsers and doesn’t add extras to cover the ones in use: acquiring lowers its available count, releasing raises it again.3
Release a browser
Release the browser when you’re done. Until you do — or until it times out — it stays
acquired and out of the pool.Limitations
A few constraints to weigh before moving a workload onto a browser pool:- No GPU browsers. GPU-accelerated browsers are on-demand only. Use
browsers.create()for WebGL, video, or canvas-heavy work. - One fixed configuration per browser pool, with
start_urlthe only setting you can override per acquisition — see Create a browser pool. - Profiles load read-only, and a browser pool holds one at a time — see Profiles with browser pools for how to persist state per user.
- Browser pool capacity counts against your concurrency limit whether or not its browsers are acquired, though idle pooled browsers aren’t billed.
- Plan-gated. Browser pools are available on the Start-Up and Enterprise plans.
Create a browser pool
Create a browser pool with a size and the configuration every browser in it should use.Acquire a browser
Acquire a browser from the browser pool. The request returns immediately if a browser is available, or waits until one becomes available. Useacquire_timeout_seconds to bound that wait.
cdp_ws_url for CDP connections and browser_live_view_url for live viewing.
Release a browser
When you’re done with a browser, release it back to the browser pool. By default, the browser instance is reused. Setreuse: false to destroy it and create a fresh one.
Reuse controls whether browser state carries across acquisitions:
reuse: true(default) returns the same browser instance to the pool without resetting it. Cookies, local storage, logged-in sessions, and open tabs persist, and the next caller to acquire it inherits that state. Fast, but not isolated between acquirers.reuse: falsedestroys the browser and refills the pool with a fresh one. Isolated and clean, at the cost of a rebuild.
Timeout behavior
Browsers wait in the browser pool indefinitely until acquired — a browser pool’stimeout_seconds only starts running once a browser is acquired. From there it behaves like a regular browser timeout: if the browser sits idle, with no CDP or live view connection, for longer than the timeout, it’s destroyed rather than returned to the pool, and the pool creates a replacement.
As a best practice, release each browser when you’re done with it — that returns it to the pool right away. The timeout is there as a backstop for browsers that never get released.
Profiles with browser pools
A profile carries login state — cookies and local storage — into a browser; use Managed Auth to populate and maintain it. Put the profile on the browser pool when every browser should share one identity; leave it off and attach it after acquiring when each task needs its own (see Per-user profiles with browser pools). A profile attached to the pool is loaded read-only. Every browser in the pool shares it, sosave_changes doesn’t apply and is silently ignored if sent — this prevents concurrent writes from corrupting the profile.
Per-user profiles with browser pools
Because that profile is shared and read-only, it can’t hold per-user login state for many users at once. To serve many users from one browser pool, create it with no profile — stealth, proxies, extensions, and viewport still live on the pool — then attach each user’s profile to the browser after you acquire it, and release withreuse: false so the browser is destroyed. Destroying it both persists that user’s profile changes and keeps their state from reaching the next acquirer.
A profile can only be loaded into a browser that was created without one, which is why the pool itself has to stay profile-free.
Refresh on profile update
Each browser loads the profile’s data at the moment it’s created, so re-saving that profile later doesn’t reach browsers that are already running. Withrefresh_on_profile_update enabled, saving the profile — after a Managed Auth login, for example — flushes every idle browser in the pool and replaces it with one that loads the updated data. Browsers that are currently acquired keep the data they started with.
It’s enabled automatically when a browser pool is created with a profile or has its profile changed, and forced to false when the profile is removed (by passing { "id": "" }). Set it to false to opt out.
refresh_on_profile_update requires a profile on the pool. Setting it to true without one returns a validation error.Sizing a browser pool
retrieve reports how many browsers are ready to acquire right now (available_count) and how many are in use (acquired_count). Watch the available count under normal load:
- Regularly at zero. Tasks are queueing behind
acquire— the pool is too small. - Steady at 10–20%. The target: enough headroom to absorb a spike without reserving capacity you don’t use.
- Consistently above 30–40%. You’re holding concurrency for browsers you never acquire, so shrink the pool.
Update a browser pool
Update the browser pool’s configuration. By default, existing idle browsers keep their current configuration and only newly created browsers use the new one. Passdiscard_all_idle: true to discard all idle browsers and rebuild them immediately with the new configuration.
API reference
See the Browser Pools API reference forretrieve, list, flush, delete, and the full parameters and response shapes of every endpoint.