Skip to main content
Browser pools let you maintain a set of pre-warmed, identically configured browsers ready for immediate use. Instead of waiting for browser creation on each request, you can acquire a browser from the pool without the startup delay and release it when done.
Browser pools are in limited preview. Book a demo to request access or learn more.

When to use pools

Pools are ideal when you need to:
  • Minimize latency for browser acquisition for more complex configurations (with profiles, proxies, etc.)
  • Run many short-lived browser tasks in parallel
  • Maintain consistent browser configuration across sessions
For one-off or long-running browser sessions, creating browsers directly with an optional extended timeout may be simpler.

Create a pool

Create a browser pool with a specified size and configuration. All browsers in the pool share the same settings.
import Kernel from '@onkernel/sdk';

const kernel = new Kernel();

const pool = await kernel.browserPools.create({
  name: "my-pool",
  size: 10,
  stealth: true,
  headless: false,
  timeout_seconds: 600,
});

console.log(pool.id);

Pool configuration options

ParameterTypeDefaultDescription
namestring-Optional unique name for the pool.
sizeinteger-Number of browsers to maintain in the pool (1-50).
fill_rate_per_minuteinteger10Percentage of the pool to fill per minute (0-25).
timeout_secondsinteger600Idle timeout for acquired browsers before destruction (60-86400).
stealthbooleanfalseEnable stealth mode to reduce bot detection.
headlessbooleanfalseRun browsers in headless mode.
profileobject-Profile to load into each browser session.
extensionsarray-List of extensions to load (max 20).
proxy_idstring-Proxy to associate with browser sessions.
viewportobject-Browser window size configuration.
kiosk_modebooleanfalseHide address bar and tabs in live view.
See Stealth Mode, Profiles, and Extensions for details on these options.

Acquire a browser

Acquire a browser from the pool. The request returns immediately if a browser is available, or waits until one becomes available. The acquire_timeout_seconds parameter controls how long to wait; it defaults to the calculated time it would take to fill the pool at the currently configured fill rate.
const browser = await kernel.browserPools.acquire("my-pool", {
  acquire_timeout_seconds: 30,
});

console.log(browser.session_id);
console.log(browser.cdp_ws_url);
The acquired browser includes all the same properties as a regular browser session, including cdp_ws_url for CDP connections and browser_live_view_url for live viewing.

Timeout behavior

Browsers remain in the pool indefinitely until acquired. Once acquired, the pool’s timeout_seconds applies just like a regular browser timeout—if the browser is idle (no CDP or live view connection) for longer than the timeout, it is destroyed and not returned to the pool. The pool will automatically create a replacement browser.

Release a browser

When you’re done with a browser, release it back to the pool. By default, the browser instance is reused. Set reuse: false to destroy it and create a fresh one.
await kernel.browserPools.release("my-pool", {
  session_id: browser.session_id,
  reuse: true,
});

Update a pool

Update the pool configuration. By default, all idle browsers are discarded and rebuilt with the new configuration.
const updatedPool = await kernel.browserPools.update("my-pool", {
  size: 20,
  stealth: true,
});
The size parameter is always required when updating a pool, even if you only want to change other settings.
By default, updating a pool discards all idle browsers and rebuilds them with the new configuration. Set discard_all_idle: false to keep existing idle browsers and only apply the new configuration to newly created browsers.

Flush idle browsers

Destroy all idle browsers in the pool. Acquired browsers are not affected. The pool will automatically refill based on the configured fill_rate_per_minute.
await kernel.browserPools.flush("my-pool");

Get pool details

Retrieve the current status and configuration of a pool.
const pool = await kernel.browserPools.retrieve("my-pool");

console.log(pool.available_count);
console.log(pool.acquired_count);

List pools

List all browser pools in your organization.
const pools = await kernel.browserPools.list();

for (const pool of pools) {
  console.log(pool.name, pool.available_count);
}

Delete a pool

Delete a browser pool and all browsers in it. By default, deletion is blocked if browsers are currently acquired. Use force: true to terminate acquired browsers and force deletion.
// Delete a pool (fails if browsers are acquired)
await kernel.browserPools.delete("my-pool");

// Force delete even if browsers are acquired
await kernel.browserPools.delete("my-pool", { force: true });

Full example

This example assumes you’ve already created a pool named “my-pool”. In practice, you’d create pools once (via the SDK, CLI, or dashboard) and then acquire from them repeatedly.
import Kernel from '@onkernel/sdk';
import { chromium } from 'playwright';

const kernel = new Kernel();

// Acquire a browser from an existing pool
const kernelBrowser = await kernel.browserPools.acquire("my-pool", {});

try {
  // Connect via CDP
  const browser = await chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
  const context = browser.contexts()[0];
  const page = context.pages()[0];

  await page.goto('https://example.com');
  const title = await page.title();
  console.log(title);
} finally {
  // Release back to pool for reuse
  await kernel.browserPools.release("my-pool", {
    session_id: kernelBrowser.session_id,
  });
}

API reference

For more details on all available endpoints and parameters, see the Browser Pools API reference.