Browser Profiles

Persist authenticated browser state for reuse

Why Browser Profiles?

Browser Profiles capture the full browser state (cookies, storage, session files) after a run completes so that future runs can skip the login or warm-up steps. They are ideal when you:

  • Need repeatable workflows that stay logged into the same account across days.
  • Want to fan out multiple workflows that all reuse the same authenticated browser state.
  • Need an audit-friendly way to persist state separate from long-lived browser sessions.

Whereas a browser session is a temporary, real-time browser, a browser profile is a reusable snapshot created from that session (or from a workflow run that persisted its session). Profiles are scoped to your organization and can be reused as often as you need.

How Browser Profiles Work

  1. Run a workflow with persist_browser_session: true or open a persistent browser session.
  2. Close the workflow run or browser session so Skyvern can upload the archived state.
  3. Create a browser profile from that source once the upload finishes.
  4. Pass browser_profile_id to subsequent workflow runs to restore the saved state instantly.

Option A — Create a Profile from a Workflow Run

Use this approach when you already ran a workflow with persist_browser_session: true. Always poll the run (e.g., GET /v1/runs/{run_id}) until it reaches status = "completed" before attempting to create the profile—Skyvern only begins uploading the archived browser state once the run finishes.

1from skyvern import Skyvern
2
3skyvern = Skyvern(api_key="YOUR_API_KEY")
4
5# After the workflow run completes, reuse its persisted session
6browser_profile = await skyvern.browser_profiles.create_browser_profile(
7 name="hn-login-profile",
8 workflow_run_id="wr_123",
9)
10print(browser_profile.browser_profile_id)

Important: Wait for Session Upload

Session persistence finishes asynchronously. Calling create_browser_profile immediately after completion usually returns a 400 such as:

  • Browser session does not have a persisted session

Add a short retry loop until the archive is ready:

1import asyncio
2import httpx
3
4async def create_profile_with_retry(
5 client: httpx.AsyncClient,
6 payload: dict,
7 retries: int = 10,
8 retry_delay: float = 1.0,
9):
10 for attempt in range(retries):
11 resp = await client.post("https://api.skyvern.com/v1/browser_profiles", json=payload)
12 if resp.status_code == 200:
13 return resp.json()
14 if resp.status_code == 400 and "persisted" in resp.text.lower():
15 await asyncio.sleep(retry_delay)
16 continue
17 resp.raise_for_status()
18 raise RuntimeError("Session never finished uploading a profile archive")

Option B — Create a Profile from a Browser Session

If you opened a persistent browser session directly (without a workflow), close it and then create a profile using the session ID:

1from skyvern import Skyvern
2
3skyvern = Skyvern(api_key="YOUR_API_KEY")
4
5browser_profile = await skyvern.browser_profiles.create_browser_profile(
6 name="support-agent",
7 browser_session_id="pbs_123",
8 description="Support queue session",
9)

Use a Browser Profile in New Workflow Runs

Once a profile exists, pass its ID when running workflows. Skyvern restores the saved cookies, storage, and local files before the first step runs, so the workflow behaves as if it never logged out.

1from skyvern import Skyvern
2
3skyvern = Skyvern(api_key="YOUR_API_KEY")
4
5workflow_run = await skyvern.run_workflow(
6 workflow_id="wf_abc",
7 browser_profile_id="bp_123",
8)
9print(workflow_run.run_id)

If the workflow also sets persist_browser_session: true, you can capture a fresh profile again at the end and keep the cycle going.