> ## Documentation Index
> Fetch the complete documentation index at: https://tbd-6fc993ce-hypeship-docker-sandboxes-integration.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Profiles

> The primitive to persist and reuse browser session state (cookies, local storage) across browsers

Profiles let you capture browser state created during a session (cookies and local storage) and reuse it in later sessions. This is the primitive to instantiate [authenticated browsers](/auth/overview).

## 1. Create a profile

When you create a [Managed Auth connection](/auth/overview), it is attached to a profile. A single profile can hold multiple auth connections — one per domain — so a browser launched with that profile is logged in to all of them at once.

You can also use profiles without Managed Auth. The first step in using profiles is to create one, optionally giving it a meaningful `name` that is unique within your organization.

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  import Kernel, { ConflictError } from '@onkernel/sdk';

  const kernel = new Kernel();

  try {
    await kernel.profiles.create({ name: 'profiles-demo' });
  } catch (err) {
    if (err instanceof ConflictError) {
      // Profile already exists
    } else {
      throw err;
    }
  }
  ```

  ```python Python theme={null}
  from kernel import Kernel, ConflictError

  kernel = Kernel()

  try:
      await kernel.profiles.create(name="profiles-demo")
  except ConflictError:
      pass
  ```
</CodeGroup>

## 2. Start a browser session using the profile and save changes

After creating the profile, reference it by its `name` or `id` when creating a browser.
Set `save_changes` to true to persist any state created during this session back into the profile when the browser is closed.

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  const kernelBrowser = await kernel.browsers.create({
    profile: {
      name: 'profiles-demo',
      save_changes: true,
    },
  });
  ```

  ```python Python theme={null}
  kernel_browser = await kernel.browsers.create(
      profile={
          "name": "profiles-demo",
          "save_changes": True,
      }
  )
  ```
</CodeGroup>

## 3. Use the browser, then close it to persist the state

After using a browser with `save_changes: true`, closing the browser will save cookies and local storage into the profile.

<Warning>
  Calling `browser.close()` does **not** save the profile state. You **must** explicitly delete the Kernel browser (or let the browser [timeout](/browsers/termination#automatic-deletion-via-timeout)) to persist the Profile.
</Warning>

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  console.log('Live view:', kernelBrowser.browser_live_view_url);

  // Navigate and create login state...

  await kernel.browsers.deleteByID(kernelBrowser.session_id);
  ```

  ```python Python theme={null}
  print("Live view:", kernel_browser.browser_live_view_url)

  # Navigate and create login state...

  await kernel.browsers.delete_by_id(kernel_browser.session_id)
  ```
</CodeGroup>

## 4. Start a new session with the saved profile (read-only)

Create another browser using the same profile name. Omitting `save_changes` leaves the stored profile untouched.

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  const kernelBrowser2 = await kernel.browsers.create({
    profile: { name: 'profiles-demo' },
  });

  console.log('Live view:', kernelBrowser2.browser_live_view_url);
  ```

  ```python Python theme={null}
  kernel_browser2 = await kernel.browsers.create(
      profile={"name": "profiles-demo"}
  )
  print("Live view:", kernel_browser2.browser_live_view_url)
  ```
</CodeGroup>

## Loading a profile into an existing browser

You can load a profile into a browser after it has been created using the [update browser endpoint](https://kernel.sh/docs/api-reference/browsers/update-browser-session).

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  // Create a browser without a profile
  const kernelBrowser = await kernel.browsers.create();

  // Later, load a profile into the browser
  await kernel.browsers.update(kernelBrowser.session_id, {
    profile: { name: 'profiles-demo' }
  });
  ```

  ```python Python theme={null}
  # Create a browser without a profile
  kernel_browser = await kernel.browsers.create()

  # Later, load a profile into the browser
  await kernel.browsers.update(kernel_browser.session_id, profile={"name": "profiles-demo"})
  ```
</CodeGroup>

<Warning>
  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.
</Warning>

## 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.

## Multiple auth connections per profile

A profile can have any number of auth connections, each for a different domain. When you launch a browser with that profile, it is already logged in to every connected domain.

### Multi-site workflows

If your agent interacts with multiple sites as part of a single workflow, attach an auth connection for each site to one profile. The browser starts logged in to all of them:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Create a single profile with auth connections for three sites
  const gmailAuth = await kernel.auth.connections.create({
    domain: 'gmail.com',
    profile_name: 'workflow-bot',
  });

  const slackAuth = await kernel.auth.connections.create({
    domain: 'slack.com',
    profile_name: 'workflow-bot',
  });

  const crmAuth = await kernel.auth.connections.create({
    domain: 'crm.example.com',
    profile_name: 'workflow-bot',
  });

  // Authenticate each connection (omitted for brevity)

  // Launch a single browser — logged in to Gmail, Slack, and the CRM
  const browser = await kernel.browsers.create({
    profile: { name: 'workflow-bot' },
    stealth: true,
  });
  ```

  ```python Python theme={null}
  # Create a single profile with auth connections for three sites
  gmail_auth = await kernel.auth.connections.create(
      domain="gmail.com",
      profile_name="workflow-bot",
  )

  slack_auth = await kernel.auth.connections.create(
      domain="slack.com",
      profile_name="workflow-bot",
  )

  crm_auth = await kernel.auth.connections.create(
      domain="crm.example.com",
      profile_name="workflow-bot",
  )

  # Authenticate each connection (omitted for brevity)

  # Launch a single browser — logged in to Gmail, Slack, and the CRM
  browser = await kernel.browsers.create(
      profile={"name": "workflow-bot"},
      stealth=True,
  )
  ```
</CodeGroup>

### User-to-profile mapping

If your platform has end users who each need their own set of authenticated accounts, map each user to a single profile. Attach all of that user's accounts as auth connections on their profile:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // For each user on your platform, create one profile
  // and attach all their accounts as auth connections
  const userId = 'user-123';

  await kernel.auth.connections.create({
    domain: 'gmail.com',
    profile_name: userId,
  });

  await kernel.auth.connections.create({
    domain: 'linkedin.com',
    profile_name: userId,
  });

  await kernel.auth.connections.create({
    domain: 'github.com',
    profile_name: userId,
  });

  // When user-123 triggers a workflow, launch a browser with their profile
  const browser = await kernel.browsers.create({
    profile: { name: userId },
    stealth: true,
  });
  ```

  ```python Python theme={null}
  # For each user on your platform, create one profile
  # and attach all their accounts as auth connections
  user_id = "user-123"

  await kernel.auth.connections.create(
      domain="gmail.com",
      profile_name=user_id,
  )

  await kernel.auth.connections.create(
      domain="linkedin.com",
      profile_name=user_id,
  )

  await kernel.auth.connections.create(
      domain="github.com",
      profile_name=user_id,
  )

  # When user-123 triggers a workflow, launch a browser with their profile
  browser = await kernel.browsers.create(
      profile={"name": user_id},
      stealth=True,
  )
  ```
</CodeGroup>

## Notes

* A profile's `name` must be unique within your organization.
* 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.
* Profile data is encrypted end to end using a per-organization key.
