---
title: "Create a browser pool"
method: POST
path: "/browser_pools"
tags: ["Browser Pools"]
---

# Create a browser pool

`POST /browser_pools`

Create a new browser pool with the specified configuration and size.
Pooled browsers load their profile read-only: any save_changes on the profile is ignored
(not rejected), so pooled browsers never persist changes back to the profile.

## Request body

- BrowserPoolCreateRequest — Parameters for creating a browser pool. All browsers in the pool will be created with the same configuration.
  - `chrome_policy` object — Custom Chrome enterprise policy overrides applied to all browsers in this pool. Keys are Chrome enterprise policy names; values must match their expected types. Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See https://chromeenterprise.google/policies/ The serialized JSON payload is capped at 5 MiB.
  - `extensions` BrowserExtension[] — List of browser extensions to load into the session. Provide each by id or name.
    - union — Extension selection for the browser session. Provide either id or name of an extension uploaded to Kernel.
      - object
        - `id` string, required — Extension ID to load for this browser session
        - `name` string — Extension name to load for this browser session (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
      - object
        - `id` string — Extension ID to load for this browser session
        - `name` string, required — Extension name to load for this browser session (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
  - `fill_rate_per_minute` integer — Percentage of the pool to fill per minute. Defaults to 25. The cap is 25 for most organizations but can be raised per-organization, so only the lower bound is enforced here.
  - `headless` boolean — If true, launches the browser using a headless image. Defaults to false.
  - `kiosk_mode` boolean — If true, launches the browser in kiosk mode to hide address bar and tabs in live view. Defaults to false.
  - `name` string — Optional name for the browser pool. Must be unique within the project.
  - `network` BrowserNetworkConfig — Network configuration for a browser session or browser pool.
    - `private_hosts` string[] — Destinations the browser reaches directly through the session's own network instead of through Kernel-managed egress — for private hosts reachable over a VPN or tunnel the session has joined (e.g. a Tailscale tailnet). By default, private IP ranges already route directly: RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), CGNAT/Tailscale (100.64.0.0/10), and IPv6 ULA (fc00::/7). An explicitly supplied list replaces those defaults with exactly the entries given, and an empty list ([]) disables them so all traffic uses Kernel-managed egress; omit private_hosts to keep the defaults. Entries are hostname patterns ("*.example.ts.net", "preview.internal") or IP/CIDR literals ("100.64.0.0/10", "10.1.30.63"). IP and CIDR entries only match URLs written with a literal IP address; they never match hostnames that resolve into the range, so private DNS names need a hostname entry even when they resolve inside the default ranges. CIDRs must be in canonical masked form (host bits zero), and only the private ranges listed above are accepted; public, loopback, link-local, and unspecified ranges are rejected. Exact IPv6 addresses must be bracketed ("[fd00::1]"); IPv6 CIDR ranges are unbracketed ("fd00::/8"). Wildcards are limited to one leading "*." over a suffix with at least two labels that is not a public suffix (so "*.co.uk" or "*.ts.net" are rejected, while "*.example.ts.net" is accepted). Hostname and IP entries may carry a port; CIDR ranges may not. Hostname entries are not resolved during validation, so callers must ensure they identify private destinations. Not related to a proxy's bypass_hosts, which selects between upstream-proxy and Kernel-managed direct egress and cannot reach into a VPN.
  - `profile` union — Profile configuration for browsers in a pool. Provide either id or name. Profiles must be created beforehand. Unlike single browser sessions, pools load the profile read-only and never persist changes back to it, so save_changes is omitted here. Any save_changes value sent on a pool profile is silently ignored rather than rejected.
    - object
      - `id` string, required — Profile ID to load for browsers in this pool
      - `name` string — Profile name to load for browsers in this pool (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
    - object
      - `id` string — Profile ID to load for browsers in this pool
      - `name` string, required — Profile name to load for browsers in this pool (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
  - `proxy_id` string — Optional proxy to associate to the browser session. Must reference a proxy in the same project as the browser session.
  - `refresh_on_profile_update` boolean — When true, flush idle browsers when the profile the pool uses is updated, so pool browsers pick up the latest profile data. When a profile is provided during creation, this defaults to true. Requires a profile to be set on the pool.
  - `region` 'us-east' | 'eu-west' — Geographic region for hosting browser sessions or pools.
  - `size` integer, required — Number of browsers to maintain in the pool. The maximum size is determined by your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit).
  - `start_url` string — Optional URL to navigate to when a new browser is warmed into the pool. Best-effort: failures to navigate do not fail pool fill. Only applied to newly-warmed browsers; browsers reused via release/acquire keep whatever URL the previous lease left them on. Accepts any URL Chromium can resolve, including chrome:// pages.
  - `stealth` boolean — If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. Defaults to false.
  - `telemetry` BrowserTelemetryRequestConfig — Telemetry request configuration for a browser session.
    - `browser` BrowserTelemetryCategoriesConfig — Per-category telemetry capture settings layered onto the default set. The operational signals (control, connection, system, captcha) are on by default and are opt-out: set one to enabled=false to stop capturing it. The CDP categories (console, network, page, interaction), screenshot and platform are off by default and are opt-in: set enabled=true to capture them.
      - `captcha` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `connection` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `console` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `control` BrowserTelemetryControlConfig — Configuration for the control category. Same enabled semantics as any other category, plus settings for the browser-control commands the CDP proxy reports.
        - `cdp` BrowserTelemetryCdpControlConfig — Settings for the cdp_command events the CDP proxy reports.
          - `excluded_methods` BrowserCdpCommandMethod[] — Methods to leave out of the cdp_command stream. Omit the list to keep the current one; send an empty list to report every supported method again. Exclusion is a telemetry setting only: an excluded command is still relayed to the browser unchanged, it simply produces no event. Use it to drop the highest-volume methods — Input.dispatchMouseEvent during a humanized cursor path, or Page.captureScreenshot under a screencast — without turning the whole category off. Excluded commands are counted in cdp_disconnect.telemetry_excluded.
        - `enabled` boolean — Whether this category is captured. Control is on by default; set false to opt out.
      - `interaction` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `network` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `page` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `platform` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `screenshot` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `system` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
        - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
    - `enabled` boolean — Request shortcut for browser telemetry capture. True enables capture; with no browser category settings it captures the default set (control, connection, system, captcha), and any browser category settings are layered onto that default set. On update, enabled=true resolves the config fresh from the default set plus any provided categories, replacing the session's current selection rather than merging onto it; omit enabled to merge categories onto the current selection instead. False stops capture on update and starts no capture on create. enabled=false cannot be combined with browser category settings.
    - `export` BrowserTelemetryExportRequestConfig — Export destinations for a session's captured telemetry, by protocol. Honored when creating a browser, including the browser a managed auth connection creates for a login. Browser pools do not support export and reject it; on a browser update it is ignored, so the session keeps the destination it was created with.
      - `otlp` BrowserTelemetryOTLPExportRequestConfig — OTLP export settings for a browser session.
        - `destination` union — OTLP destination selection. Provide either id or name. The destination must exist in the project the request resolves to.
          - object
            - `id` string, required — OTLP destination ID
            - `name` string — OTLP destination name
          - object
            - `id` string — OTLP destination ID
            - `name` string, required — OTLP destination name
        - `enabled` boolean — Whether to export captured telemetry over OTLP. Setting destination implies enabled=true, so this only needs to be set explicitly to disable export (enabled=false with a destination is rejected).
  - `timeout_seconds` integer — Default idle timeout in seconds for browsers acquired from this pool before they are destroyed. Defaults to 600 seconds. Minimum 10, maximum 259200 (72 hours).
  - `viewport` BrowserViewport — Initial browser window size in pixels with optional refresh rate. If omitted, image defaults apply (1920x1080@25). For GPU images, the default is 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For GPU images, recommended presets use one of these resolutions with refresh rates 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view or recording behavior. If refresh_rate is not provided, it will be automatically determined based on the resolution (higher resolutions use lower refresh rates to keep bandwidth reasonable).
    - `height` integer, required — Browser window height in pixels. Any positive integer is accepted.
    - `refresh_rate` integer — Display refresh rate in Hz. Any positive integer is accepted; if omitted, automatically determined from width and height.
    - `width` integer, required — Browser window width in pixels. Any positive integer is accepted.

## Response `201`

Browser pool created successfully

- BrowserPool — A browser pool containing multiple identically configured browsers.
  - `acquired_count` integer, required — Number of browsers currently acquired from the pool
  - `available_count` integer, required — Number of browsers currently available in the pool
  - `browser_pool_config` BrowserPoolConfig, required — Effective browser pool configuration returned by the API.
    - `chrome_policy` object — Custom Chrome enterprise policy overrides applied to all browsers in this pool. Keys are Chrome enterprise policy names; values must match their expected types. Blocked: kernel-managed policies (extensions, proxy, CDP/automation). See https://chromeenterprise.google/policies/ The serialized JSON payload is capped at 5 MiB.
    - `extensions` BrowserExtension[] — List of browser extensions to load into the session. Provide each by id or name.
      - union — Extension selection for the browser session. Provide either id or name of an extension uploaded to Kernel.
        - object
          - `id` string, required — Extension ID to load for this browser session
          - `name` string — Extension name to load for this browser session (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
        - object
          - `id` string — Extension ID to load for this browser session
          - `name` string, required — Extension name to load for this browser session (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
    - `fill_rate_per_minute` integer — Percentage of the pool to fill per minute. The cap is 25 for most organizations but can be raised per-organization, so only the lower bound is enforced here.
    - `headless` boolean — If true, launches the browser using a headless image.
    - `kiosk_mode` boolean — If true, launches the browser in kiosk mode to hide address bar and tabs in live view.
    - `name` string — Optional name for the browser pool. Must be unique within the project.
    - `network` BrowserNetworkConfig — Network configuration for a browser session or browser pool.
      - `private_hosts` string[] — Destinations the browser reaches directly through the session's own network instead of through Kernel-managed egress — for private hosts reachable over a VPN or tunnel the session has joined (e.g. a Tailscale tailnet). By default, private IP ranges already route directly: RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), CGNAT/Tailscale (100.64.0.0/10), and IPv6 ULA (fc00::/7). An explicitly supplied list replaces those defaults with exactly the entries given, and an empty list ([]) disables them so all traffic uses Kernel-managed egress; omit private_hosts to keep the defaults. Entries are hostname patterns ("*.example.ts.net", "preview.internal") or IP/CIDR literals ("100.64.0.0/10", "10.1.30.63"). IP and CIDR entries only match URLs written with a literal IP address; they never match hostnames that resolve into the range, so private DNS names need a hostname entry even when they resolve inside the default ranges. CIDRs must be in canonical masked form (host bits zero), and only the private ranges listed above are accepted; public, loopback, link-local, and unspecified ranges are rejected. Exact IPv6 addresses must be bracketed ("[fd00::1]"); IPv6 CIDR ranges are unbracketed ("fd00::/8"). Wildcards are limited to one leading "*." over a suffix with at least two labels that is not a public suffix (so "*.co.uk" or "*.ts.net" are rejected, while "*.example.ts.net" is accepted). Hostname and IP entries may carry a port; CIDR ranges may not. Hostname entries are not resolved during validation, so callers must ensure they identify private destinations. Not related to a proxy's bypass_hosts, which selects between upstream-proxy and Kernel-managed direct egress and cannot reach into a VPN.
    - `profile` union — Profile configuration for browsers in a pool. Provide either id or name. Profiles must be created beforehand. Unlike single browser sessions, pools load the profile read-only and never persist changes back to it, so save_changes is omitted here. Any save_changes value sent on a pool profile is silently ignored rather than rejected.
      - object
        - `id` string, required — Profile ID to load for browsers in this pool
        - `name` string — Profile name to load for browsers in this pool (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
      - object
        - `id` string — Profile ID to load for browsers in this pool
        - `name` string, required — Profile name to load for browsers in this pool (instead of id). Must be 1-255 characters, using letters, numbers, dots, underscores, or hyphens.
    - `proxy_id` string — Optional proxy associated to the browser session. References a proxy in the same project as the browser session.
    - `refresh_on_profile_update` boolean — When true, flush idle browsers when the profile the pool uses is updated, so pool browsers pick up the latest profile data. When a profile is provided during creation, this defaults to true. Requires a profile to be set on the pool.
    - `size` integer, required — Number of browsers maintained in the pool. The maximum size is determined by your organization's pooled sessions limit (the sum of all pool sizes cannot exceed your limit).
    - `start_url` string — Optional URL to navigate to when a new browser is warmed into the pool. Best-effort: failures to navigate do not fail pool fill. Only applied to newly-warmed browsers; browsers reused via release/acquire keep whatever URL the previous lease left them on. Accepts any URL Chromium can resolve, including chrome:// pages.
    - `stealth` boolean — If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms.
    - `telemetry` BrowserTelemetryConfig — Active telemetry configuration for a browser session.
      - `browser` BrowserTelemetryCategoriesConfig — Per-category telemetry capture settings layered onto the default set. The operational signals (control, connection, system, captcha) are on by default and are opt-out: set one to enabled=false to stop capturing it. The CDP categories (console, network, page, interaction), screenshot and platform are off by default and are opt-in: set enabled=true to capture them.
        - `captcha` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `connection` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `console` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `control` BrowserTelemetryControlConfig — Configuration for the control category. Same enabled semantics as any other category, plus settings for the browser-control commands the CDP proxy reports.
          - `cdp` BrowserTelemetryCdpControlConfig — Settings for the cdp_command events the CDP proxy reports.
            - `excluded_methods` BrowserCdpCommandMethod[] — Methods to leave out of the cdp_command stream. Omit the list to keep the current one; send an empty list to report every supported method again. Exclusion is a telemetry setting only: an excluded command is still relayed to the browser unchanged, it simply produces no event. Use it to drop the highest-volume methods — Input.dispatchMouseEvent during a humanized cursor path, or Page.captureScreenshot under a screencast — without turning the whole category off. Excluded commands are counted in cdp_disconnect.telemetry_excluded.
          - `enabled` boolean — Whether this category is captured. Control is on by default; set false to opt out.
        - `interaction` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `network` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `page` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `platform` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `screenshot` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
        - `system` BrowserTelemetryCategoryConfig — Per-category telemetry configuration.
          - `enabled` boolean — Whether this category is captured. Operational categories (control, connection, system, captcha) default to true; set false to opt out. CDP categories (console, network, page, interaction), screenshot and platform default to false; set true to opt in.
      - `export` BrowserTelemetryExportConfig — Active export state for a session's captured telemetry, by protocol.
        - `otlp` BrowserTelemetryOTLPExportConfig — Active OTLP export state for a browser session.
          - `destination` string — ID of the OTLP destination the session is bound to. Omitted when the session is not exporting.
          - `enabled` boolean — Whether the session is exporting captured telemetry over OTLP.
    - `timeout_seconds` integer — Default idle timeout in seconds for browsers acquired from this pool before they are destroyed. Minimum 10, maximum 259200 (72 hours).
    - `viewport` BrowserViewport — Initial browser window size in pixels with optional refresh rate. If omitted, image defaults apply (1920x1080@25). For GPU images, the default is 1920x1080@60. Arbitrary viewport dimensions and refresh rates are accepted. Known-good presets include: 2560x1440@10, 1920x1080@25, 1920x1200@25, 1440x900@25, 1280x800@60, 1024x768@60, 1200x800@60, 768x1024@60, 390x844@60. For GPU images, recommended presets use one of these resolutions with refresh rates 60, 30, 25, or 10: 800x600, 960x720, 1024x576, 1024x768, 1152x648, 1200x800, 1280x720, 1368x768, 1440x900, 1600x900, 1920x1080, 1920x1200, 390x844, 360x250, 768x1024, 800x1600. Viewports outside this list may exhibit unstable live view or recording behavior. If refresh_rate is not provided, it will be automatically determined based on the resolution (higher resolutions use lower refresh rates to keep bandwidth reasonable).
      - `height` integer, required — Browser window height in pixels. Any positive integer is accepted.
      - `refresh_rate` integer — Display refresh rate in Hz. Any positive integer is accepted; if omitted, automatically determined from width and height.
      - `width` integer, required — Browser window width in pixels. Any positive integer is accepted.
  - `created_at` string, date-time, required — Timestamp when the browser pool was created
  - `extension_ids` string[], required — Resolved extension IDs attached to the pool, in configured load order. Empty when no extensions are attached. Authoritative for programmatic consumers; the extensions inside `browser_pool_config` reflect the configured selector (echoed as sent on create).
  - `id` string, required — Unique identifier for the browser pool
  - `name` string — Browser pool name, if set
  - `profile_id` string — Resolved profile ID the pool is attached to. Omitted when no profile is attached. Authoritative for programmatic consumers; the profile inside `browser_pool_config` reflects the configured selector (echoed as sent on create).
  - `region` 'us-east' | 'eu-west', required — Geographic region for hosting browser sessions or pools.

## Other responses

- `400` — Bad Request – invalid input
- `401` — Unauthorized – missing or invalid authorization token
- `403` — Forbidden – insufficient permissions or plan
- `409` — Conflict – resource already exists
- `429` — Too Many Requests – rate limit exceeded
- `500` — Internal Server Error

---

[API](https://skmtc.net/onkernel/apis/kernel-api.md) · [All operations](https://skmtc.net/onkernel/apis/kernel-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/onkernel/kernel-api/revisions/858365328f92/schema)
