From d7d7a201be6fc2aa116de9e8d6db70ca2d527eed Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:38:09 +0000 Subject: [PATCH 1/8] docs(pools): document per-user profile persistence through pools Clarify that while a pool-config profile is read-only, attaching a per-user profile after acquiring a browser and releasing with reuse:false does persist changes. Adds a dedicated overview section, a rewritten FAQ answer, a new FAQ, and cross-links from profiles. Co-Authored-By: Claude Opus 4.8 --- auth/profiles.mdx | 6 ++- browsers/pools/faq.mdx | 11 ++++- browsers/pools/overview.mdx | 87 +++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/auth/profiles.mdx b/auth/profiles.mdx index 4f47c72..72ed8c3 100644 --- a/auth/profiles.mdx +++ b/auth/profiles.mdx @@ -257,6 +257,10 @@ if err != nil { You cannot load a profile into a browser that was already created with a profile. The browser must have been created without any profile configuration. + +This is also how you use [browser pools](/browsers/pools/overview#per-user-profiles-with-pools) with per-user profiles: acquire a profile-free browser from the pool, load the user's profile with `save_changes: true`, then release it with `reuse: false` so the changes persist and the browser is destroyed rather than handed to the next user. + + ## Other ways to use profiles The API and SDKs support listing, deleting, and downloading profile data as JSON. See the [API reference](https://kernel.sh/docs/api-reference/profiles/list-profiles) for more details. @@ -484,5 +488,5 @@ _ = browser - Profiles store cookies and local storage. Start the session with `save_changes: true` to write changes back when the browser is closed. - To keep a profile immutable for a run, omit `save_changes` (default) when creating the browser. - Multiple browsers in parallel can use the same profile, but only one browser should write (`save_changes: true`) to it at a time. Parallel browsers with `save_changes: true` may cause profile corruption and unpredictable behavior. -- `save_changes` applies only to single browser sessions (`kernel.browsers.create()`). [Browser pools](/browsers/pools/overview) load a profile read-only and never persist changes back to it; `save_changes` sent on a pool's profile is silently ignored. +- `save_changes` applies to a profile attached to a single browser — either at creation (`kernel.browsers.create()`) or loaded afterward with `kernel.browsers.update()`. A profile set on a [browser pool's](/browsers/pools/overview) config is loaded read-only and never persisted; `save_changes` sent on a pool's profile is silently ignored. To persist per-user state through a pool, attach the profile after acquiring the browser and release with `reuse: false` — see [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools). - Profile data is encrypted end to end using a per-organization key. diff --git a/browsers/pools/faq.mdx b/browsers/pools/faq.mdx index e78e791..421a69f 100644 --- a/browsers/pools/faq.mdx +++ b/browsers/pools/faq.mdx @@ -40,7 +40,16 @@ If you've explicitly disabled `refresh_on_profile_update`, you can still force t ### Can pooled browsers save changes back to a profile? -No. A profile attached to a pool is loaded read-only — pooled browsers never persist changes back to the profile, so `save_changes` does not apply to pools. Sending `save_changes` on a pool's profile is silently ignored (it is not rejected), so reusing a single-session profile object won't error. To capture profile state, use a single browser session instead: `kernel.browsers.create({ profile: { name, save_changes: true } })`. +Not at the pool level, but yes per session. These are two different things: + +- **A profile set on the pool config** is loaded read-only. Every browser in the pool shares it and would try to save concurrently, so `save_changes` does not apply to pools — sending it on a pool's profile is silently ignored (not rejected). This is by design: it prevents profile corruption and the ambiguity of which idle browser's state would "win". +- **A profile attached to a single browser _after_ you acquire it** does persist. Create the pool with no profile, acquire a browser, attach a per-user profile with `save_changes: true` via `kernel.browsers.update()`, then release with `reuse: false` so the browser is destroyed (which flushes the profile) instead of returning to the pool. + +The second pattern is the recommended way to load many per-user profiles through a pool's pre-warmed browsers — see [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools). + +### How do I use a different profile per user with a pool and persist each user's login state? + +Create the pool with **no profile**, then per user: acquire a browser, attach that user's profile with `save_changes: true` using `kernel.browsers.update()`, run your automation, and release with `reuse: false`. Releasing with `reuse: false` destroys the browser instead of returning it to the pool, which both persists the profile changes and guarantees no state leaks to the next user. The pool then refills automatically with fresh, profile-free browsers. See [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools) for the full flow with code. ### Should I set `reuse: true` or `reuse: false` when releasing? diff --git a/browsers/pools/overview.mdx b/browsers/pools/overview.mdx index 0fc3d6a..5c5cf62 100644 --- a/browsers/pools/overview.mdx +++ b/browsers/pools/overview.mdx @@ -202,6 +202,93 @@ if err := client.BrowserPools.Release(ctx, "my-pool", kernel.BrowserPoolReleaseP ``` +## Per-user profiles with pools + +A profile attached to the pool config is [read-only](#create-a-pool-of-reserved-browsers) and shared by every browser, so it can't hold per-user login state. To use a pool's pre-warmed browsers to load many different per-user profiles **and** persist each user's state, attach the profile to the browser *after* you acquire it, then destroy the browser on release: + +1. **Create the pool with no profile.** A profile can only be loaded into a browser that was created without one, so the pool must be profile-free. +2. **Acquire a browser** from the pool. +3. **Attach the user's profile** with `save_changes: true` using `kernel.browsers.update()`. +4. **Run your automation, then release with `reuse: false`.** This destroys the browser instead of returning it to the pool — which both persists the profile changes and prevents state from leaking to the next user. + + +```typescript Typescript/Javascript +// Create the pool once, with no profile attached +const pool = await kernel.browserPools.create({ name: "my-pool", size: 10 }); + +// Then, per user: +const browser = await kernel.browserPools.acquire("my-pool", {}); + +// Load this user's profile and persist any changes on destroy +await kernel.browsers.update(browser.session_id, { + profile: { name: userId, save_changes: true }, +}); + +// ... run your automation against browser.cdp_ws_url ... + +// Destroy on release so the profile persists and no state leaks to the next user +await kernel.browserPools.release("my-pool", { + session_id: browser.session_id, + reuse: false, +}); +``` + +```python Python +# Create the pool once, with no profile attached +pool = kernel.browser_pools.create(name="my-pool", size=10) + +# Then, per user: +browser = kernel.browser_pools.acquire("my-pool") + +# Load this user's profile and persist any changes on destroy +kernel.browsers.update( + browser.session_id, + profile={"name": user_id, "save_changes": True}, +) + +# ... run your automation against browser.cdp_ws_url ... + +# Destroy on release so the profile persists and no state leaks to the next user +kernel.browser_pools.release( + "my-pool", + session_id=browser.session_id, + reuse=False, +) +``` + +```go Go +// Acquire a browser from a profile-free pool +browser, err := client.BrowserPools.Acquire(ctx, "my-pool", kernel.BrowserPoolAcquireParams{}) +if err != nil { + panic(err) +} + +// Load this user's profile and persist any changes on destroy +if _, err := client.Browsers.Update(ctx, browser.SessionID, kernel.BrowserUpdateParams{ + Profile: shared.BrowserProfileParam{ + Name: kernel.String(userID), + SaveChanges: kernel.Bool(true), + }, +}); err != nil { + panic(err) +} + +// ... run your automation against browser.CdpWsURL ... + +// Destroy on release so the profile persists and no state leaks to the next user +if err := client.BrowserPools.Release(ctx, "my-pool", kernel.BrowserPoolReleaseParams{ + SessionID: browser.SessionID, + Reuse: kernel.Bool(false), +}); err != nil { + panic(err) +} +``` + + + +Releasing with `reuse: false` triggers a pool refill at the configured [fill rate](https://kernel.sh/docs/api-reference/browser-pools/create-a-browser-pool#body-fill-rate-per-minute), so the pool tops back up to `size` with fresh, profile-free browsers ready for the next user. + + ## Update a pool Update the pool configuration. By default, existing idle browsers keep their current configuration and only newly created browsers use the new one. Pass `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration. From 4cf0d1a45c9c8330752606fa1367953ddcf44f14 Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:50:39 +0000 Subject: [PATCH 2/8] docs(pools): say persist state, not login state, in FAQ heading Co-Authored-By: Claude Opus 4.8 --- browsers/pools/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browsers/pools/faq.mdx b/browsers/pools/faq.mdx index 421a69f..52bdd4c 100644 --- a/browsers/pools/faq.mdx +++ b/browsers/pools/faq.mdx @@ -47,7 +47,7 @@ Not at the pool level, but yes per session. These are two different things: The second pattern is the recommended way to load many per-user profiles through a pool's pre-warmed browsers — see [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools). -### How do I use a different profile per user with a pool and persist each user's login state? +### How do I use a different profile per user with a pool and persist each user's state? Create the pool with **no profile**, then per user: acquire a browser, attach that user's profile with `save_changes: true` using `kernel.browsers.update()`, run your automation, and release with `reuse: false`. Releasing with `reuse: false` destroys the browser instead of returning it to the pool, which both persists the profile changes and guarantees no state leaks to the next user. The pool then refills automatically with fresh, profile-free browsers. See [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools) for the full flow with code. From c26f6c3c84d998b8ffea8b561aaf88c63855c25b Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:54:40 +0000 Subject: [PATCH 3/8] docs(pools): move per-user profiles section after refresh on profile update Co-Authored-By: Claude Opus 4.8 --- browsers/pools/overview.mdx | 128 ++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/browsers/pools/overview.mdx b/browsers/pools/overview.mdx index 5c5cf62..88c6231 100644 --- a/browsers/pools/overview.mdx +++ b/browsers/pools/overview.mdx @@ -202,6 +202,70 @@ if err := client.BrowserPools.Release(ctx, "my-pool", kernel.BrowserPoolReleaseP ``` +## Update a pool + +Update the pool configuration. By default, existing idle browsers keep their current configuration and only newly created browsers use the new one. Pass `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration. + + +```typescript Typescript/Javascript +const updatedPool = await kernel.browserPools.update("my-pool", { + size: 20, + stealth: true, +}); +``` + +```python Python +updated_pool = kernel.browser_pools.update( + "my-pool", + size=20, + stealth=True, +) +``` + +```go Go +updatedPool, err := client.BrowserPools.Update(ctx, "my-pool", kernel.BrowserPoolUpdateParams{ + Size: 20, + Stealth: kernel.Bool(true), +}) +if err != nil { + panic(err) +} +_ = updatedPool +``` + + + +The `size` parameter is always required when updating a pool, even if you only want to change other settings. + + +By default (`discard_all_idle: false`), updating a pool leaves existing idle browsers untouched — they keep their original configuration, and only browsers created after the update use the new configuration. Set `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration. + +## Refresh on profile update + +When a pool is configured with a [profile](/auth/profiles), the profile data is loaded into each browser when it's created. Normally, updating the profile's contents (for example, re-saving cookies or auth state to the same profile) does not propagate to already-warmed browsers — only newly-filled browsers use the updated profile. + +`refresh_on_profile_update` is automatically set to `true` when a pool is created with a profile, or when an existing pool's profile is changed. This ensures that acquired browsers always get the latest profile data without manual intervention. You can explicitly set it to `false` to opt out. + +When a pool's profile is removed (by passing `{ "id": "" }`), `refresh_on_profile_update` is forced to `false`. + + +`refresh_on_profile_update` requires a profile to be set on the pool. Setting it explicitly to `true` on a pool without a profile returns a validation error. When created without a profile, it defaults to `false`. + + +### How it works + +When a profile is saved (for example, after a successful [Managed Auth](/auth/overview) login or a `save_changes` browser session), Kernel checks whether any browser pools use that profile with `refresh_on_profile_update` enabled. If so, all idle browsers in each matching pool are flushed — they are replaced with fresh browsers that load the updated profile. Acquired browsers are not affected; they continue running with the profile data they were created with. + + +Reused browsers keep the configuration they were created with. A plain `update()` rebuilds nothing that already exists — it only changes the config used for future browsers. To rebuild the idle browsers too, pass `discard_all_idle: true` (or call [`flush()`](#flush-idle-browsers)). Either way, browsers that are acquired during an update are never touched: an in-use browser keeps its original configuration, and if you then release it with `reuse: true` (the default) it re-enters the pool still carrying that stale configuration and keeps getting handed out that way. + +You have three ways to get an in-use browser onto the new configuration: + +- **Prevent it on release:** release with `reuse: false`. The browser is destroyed and rebuilt with the current pool configuration instead of the old one returning to the pool. +- **Let it expire:** don't release the acquired browser for reuse. Let it reach its `timeout_seconds` while idle, at which point it's destroyed and the pool refills automatically with the new configuration. +- **Clean it up after the fact:** [`flush()`](#flush-idle-browsers) the pool, or run a later `update()` with `discard_all_idle: true`, once the in-use browsers have been released. + + ## Per-user profiles with pools A profile attached to the pool config is [read-only](#create-a-pool-of-reserved-browsers) and shared by every browser, so it can't hold per-user login state. To use a pool's pre-warmed browsers to load many different per-user profiles **and** persist each user's state, attach the profile to the browser *after* you acquire it, then destroy the browser on release: @@ -289,70 +353,6 @@ if err := client.BrowserPools.Release(ctx, "my-pool", kernel.BrowserPoolReleaseP Releasing with `reuse: false` triggers a pool refill at the configured [fill rate](https://kernel.sh/docs/api-reference/browser-pools/create-a-browser-pool#body-fill-rate-per-minute), so the pool tops back up to `size` with fresh, profile-free browsers ready for the next user. -## Update a pool - -Update the pool configuration. By default, existing idle browsers keep their current configuration and only newly created browsers use the new one. Pass `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration. - - -```typescript Typescript/Javascript -const updatedPool = await kernel.browserPools.update("my-pool", { - size: 20, - stealth: true, -}); -``` - -```python Python -updated_pool = kernel.browser_pools.update( - "my-pool", - size=20, - stealth=True, -) -``` - -```go Go -updatedPool, err := client.BrowserPools.Update(ctx, "my-pool", kernel.BrowserPoolUpdateParams{ - Size: 20, - Stealth: kernel.Bool(true), -}) -if err != nil { - panic(err) -} -_ = updatedPool -``` - - - -The `size` parameter is always required when updating a pool, even if you only want to change other settings. - - -By default (`discard_all_idle: false`), updating a pool leaves existing idle browsers untouched — they keep their original configuration, and only browsers created after the update use the new configuration. Set `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration. - -## Refresh on profile update - -When a pool is configured with a [profile](/auth/profiles), the profile data is loaded into each browser when it's created. Normally, updating the profile's contents (for example, re-saving cookies or auth state to the same profile) does not propagate to already-warmed browsers — only newly-filled browsers use the updated profile. - -`refresh_on_profile_update` is automatically set to `true` when a pool is created with a profile, or when an existing pool's profile is changed. This ensures that acquired browsers always get the latest profile data without manual intervention. You can explicitly set it to `false` to opt out. - -When a pool's profile is removed (by passing `{ "id": "" }`), `refresh_on_profile_update` is forced to `false`. - - -`refresh_on_profile_update` requires a profile to be set on the pool. Setting it explicitly to `true` on a pool without a profile returns a validation error. When created without a profile, it defaults to `false`. - - -### How it works - -When a profile is saved (for example, after a successful [Managed Auth](/auth/overview) login or a `save_changes` browser session), Kernel checks whether any browser pools use that profile with `refresh_on_profile_update` enabled. If so, all idle browsers in each matching pool are flushed — they are replaced with fresh browsers that load the updated profile. Acquired browsers are not affected; they continue running with the profile data they were created with. - - -Reused browsers keep the configuration they were created with. A plain `update()` rebuilds nothing that already exists — it only changes the config used for future browsers. To rebuild the idle browsers too, pass `discard_all_idle: true` (or call [`flush()`](#flush-idle-browsers)). Either way, browsers that are acquired during an update are never touched: an in-use browser keeps its original configuration, and if you then release it with `reuse: true` (the default) it re-enters the pool still carrying that stale configuration and keeps getting handed out that way. - -You have three ways to get an in-use browser onto the new configuration: - -- **Prevent it on release:** release with `reuse: false`. The browser is destroyed and rebuilt with the current pool configuration instead of the old one returning to the pool. -- **Let it expire:** don't release the acquired browser for reuse. Let it reach its `timeout_seconds` while idle, at which point it's destroyed and the pool refills automatically with the new configuration. -- **Clean it up after the fact:** [`flush()`](#flush-idle-browsers) the pool, or run a later `update()` with `discard_all_idle: true`, once the in-use browsers have been released. - - ## Flush idle browsers Destroy all idle browsers in the pool. Acquired browsers are not affected. The pool will automatically refill with the pool's specified configuration. From bed3e2717d5ed4a7822da8bbbbd8d4da5a0f5912 Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:04:40 +0000 Subject: [PATCH 4/8] docs(pools): clarify pool profile can't hold per-user state across users Co-Authored-By: Claude Opus 4.8 --- browsers/pools/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browsers/pools/overview.mdx b/browsers/pools/overview.mdx index 88c6231..c5f4974 100644 --- a/browsers/pools/overview.mdx +++ b/browsers/pools/overview.mdx @@ -268,7 +268,7 @@ You have three ways to get an in-use browser onto the new configuration: ## Per-user profiles with pools -A profile attached to the pool config is [read-only](#create-a-pool-of-reserved-browsers) and shared by every browser, so it can't hold per-user login state. To use a pool's pre-warmed browsers to load many different per-user profiles **and** persist each user's state, attach the profile to the browser *after* you acquire it, then destroy the browser on release: +A profile attached to the pool config is [read-only](#create-a-pool-of-reserved-browsers) and shared by every browser, so it can't hold per-user login state across many users in a single pool. To use a pool's pre-warmed browsers to load many different per-user profiles **and** persist each user's state, attach the profile to the browser *after* you acquire it, then destroy the browser on release: 1. **Create the pool with no profile.** A profile can only be loaded into a browser that was created without one, so the pool must be profile-free. 2. **Acquire a browser** from the pool. From 4854b698420ce20c5b10b0a4b97ab5d27a704d8b Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:08:35 +0000 Subject: [PATCH 5/8] docs(pools): note pools should be declared outside workload runtime in examples Co-Authored-By: Claude Opus 4.8 --- browsers/pools/overview.mdx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/browsers/pools/overview.mdx b/browsers/pools/overview.mdx index c5f4974..6ebcbf6 100644 --- a/browsers/pools/overview.mdx +++ b/browsers/pools/overview.mdx @@ -277,10 +277,10 @@ A profile attached to the pool config is [read-only](#create-a-pool-of-reserved- ```typescript Typescript/Javascript -// Create the pool once, with no profile attached +// Declare the pool once, separately from your workload runtime, with no profile attached const pool = await kernel.browserPools.create({ name: "my-pool", size: 10 }); -// Then, per user: +// Later, at runtime, acquire from the pool per user: const browser = await kernel.browserPools.acquire("my-pool", {}); // Load this user's profile and persist any changes on destroy @@ -298,10 +298,10 @@ await kernel.browserPools.release("my-pool", { ``` ```python Python -# Create the pool once, with no profile attached +# Declare the pool once, separately from your workload runtime, with no profile attached pool = kernel.browser_pools.create(name="my-pool", size=10) -# Then, per user: +# Later, at runtime, acquire from the pool per user: browser = kernel.browser_pools.acquire("my-pool") # Load this user's profile and persist any changes on destroy @@ -321,7 +321,8 @@ kernel.browser_pools.release( ``` ```go Go -// Acquire a browser from a profile-free pool +// Declare the pool once, separately from your workload runtime, with no profile attached. +// Later, at runtime, acquire from the pool per user: browser, err := client.BrowserPools.Acquire(ctx, "my-pool", kernel.BrowserPoolAcquireParams{}) if err != nil { panic(err) From c13782f0c8e74aad5cd5680045b25dcab4a3d98e Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:29:42 +0000 Subject: [PATCH 6/8] docs(pools): drop duplicate per-user FAQ entry Covered by the save-changes FAQ answer above and the overview section. Co-Authored-By: Claude Opus 4.8 --- browsers/pools/faq.mdx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/browsers/pools/faq.mdx b/browsers/pools/faq.mdx index 52bdd4c..b53637e 100644 --- a/browsers/pools/faq.mdx +++ b/browsers/pools/faq.mdx @@ -47,10 +47,6 @@ Not at the pool level, but yes per session. These are two different things: The second pattern is the recommended way to load many per-user profiles through a pool's pre-warmed browsers — see [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools). -### How do I use a different profile per user with a pool and persist each user's state? - -Create the pool with **no profile**, then per user: acquire a browser, attach that user's profile with `save_changes: true` using `kernel.browsers.update()`, run your automation, and release with `reuse: false`. Releasing with `reuse: false` destroys the browser instead of returning it to the pool, which both persists the profile changes and guarantees no state leaks to the next user. The pool then refills automatically with fresh, profile-free browsers. See [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools) for the full flow with code. - ### Should I set `reuse: true` or `reuse: false` when releasing? Use `reuse: true` (default) for efficiency. Only use `reuse: false` when you suspect browser state corruption or need a guaranteed clean browser session. From e1b54a3697ac79390b772001fbefc2417f4abf84 Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:31:25 +0000 Subject: [PATCH 7/8] docs(profiles): reframe pools note to lead with the use case Co-Authored-By: Claude Opus 4.8 --- auth/profiles.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/profiles.mdx b/auth/profiles.mdx index 72ed8c3..7d06998 100644 --- a/auth/profiles.mdx +++ b/auth/profiles.mdx @@ -258,7 +258,7 @@ You cannot load a profile into a browser that was already created with a profile -This is also how you use [browser pools](/browsers/pools/overview#per-user-profiles-with-pools) with per-user profiles: acquire a profile-free browser from the pool, load the user's profile with `save_changes: true`, then release it with `reuse: false` so the changes persist and the browser is destroyed rather than handed to the next user. +To use profiles with [browser pools](/browsers/pools/overview#per-user-profiles-with-pools) — a different profile per user, with each user's state persisted — acquire a profile-free browser from the pool, load the user's profile here with `save_changes: true`, then release it with `reuse: false` so the changes persist and the browser is destroyed rather than handed to the next user. See [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools) for the full flow. ## Other ways to use profiles From d4ebf81279e0f11d5c17e575ce1f43e688afff2f Mon Sep 17 00:00:00 2001 From: dprevoznik <58714078+dprevoznik@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:34:57 +0000 Subject: [PATCH 8/8] docs(profiles): simplify pools note to a pointer to the FAQ Co-Authored-By: Claude Opus 4.8 --- auth/profiles.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth/profiles.mdx b/auth/profiles.mdx index 7d06998..5bb0cf4 100644 --- a/auth/profiles.mdx +++ b/auth/profiles.mdx @@ -258,7 +258,7 @@ You cannot load a profile into a browser that was already created with a profile -To use profiles with [browser pools](/browsers/pools/overview#per-user-profiles-with-pools) — a different profile per user, with each user's state persisted — acquire a profile-free browser from the pool, load the user's profile here with `save_changes: true`, then release it with `reuse: false` so the changes persist and the browser is destroyed rather than handed to the next user. See [Per-user profiles with pools](/browsers/pools/overview#per-user-profiles-with-pools) for the full flow. +To use profiles with browser pools, read: [Can pooled browsers save changes back to a profile?](/browsers/pools/faq#can-pooled-browsers-save-changes-back-to-a-profile) ## Other ways to use profiles