Skip to main content
A Browser Session is a live browser instance that persists cookies, local storage, and page state between task or workflow runs. Think of it as keeping a browser tab open. Use sessions when you need back-to-back tasks to share state, human-in-the-loop approval, or real-time agents.

Create a session

Start a session with optional configuration for timeout, proxy, browser type, and extensions.
import asyncio
from skyvern import Skyvern

async def main():
    client = Skyvern(api_key="YOUR_API_KEY")

    session = await client.create_browser_session(
        timeout=60,                    # Max 60 minutes
        proxy_location="RESIDENTIAL",  # US residential proxy
        browser_type="chrome",         # Chrome or Edge
        extensions=["ad-blocker"],     # Optional extensions
    )

    print(f"Session ID: {session.browser_session_id}")
    print(f"Status: {session.status}")

asyncio.run(main())
Parameters:
ParameterTypeDescription
timeoutintegerSession lifetime in minutes. Min: 5, Max: 1440 (24 hours). Default: 60
proxy_locationstringGeographic proxy location (Cloud only). See Proxy & Geolocation for available options
browser_typestringBrowser type: chrome or msedge
extensionsarrayExtensions to install: ad-blocker, captcha-solver
Example response:
{
  "browser_session_id": "pbs_490705123456789012",
  "organization_id": "o_485917350850524254",
  "status": "running",
  "timeout": 60,
  "browser_type": "chrome",
  "extensions": ["ad-blocker"],
  "vnc_streaming_supported": true,
  "app_url": "https://app.skyvern.com/browser-session/pbs_490705123456789012",
  "started_at": "2026-02-01T10:30:03.110Z",
  "created_at": "2026-02-01T10:30:00.000Z",
  "modified_at": "2026-02-01T10:30:03.251Z"
}
Session statuses:
StatusDescription
runningBrowser is live and accepting tasks. This is the status returned on creation. The browser launches within seconds.
closedSession was closed manually or by timeout. No further tasks can run.
Sessions close automatically when the timeout expires, even if a task is still running. The timeout countdown begins when the browser launches. Set timeouts with enough margin for your longest expected task.

Run tasks with a session

Pass browser_session_id to run_task to execute tasks in an existing session. Each task continues from where the previous one left off: same page, same cookies, same form data.
import asyncio
from skyvern import Skyvern

async def main():
    client = Skyvern(api_key="YOUR_API_KEY")

    # Create session
    session = await client.create_browser_session(timeout=30)
    session_id = session.browser_session_id

    try:
        # Task 1: Login (wait for completion before continuing)
        await client.run_task(
            prompt="Login with username 'support@company.com'",
            url="https://dashboard.example.com/login",
            browser_session_id=session_id,
            wait_for_completion=True,
        )

        # Task 2: Search (already logged in from Task 1)
        result = await client.run_task(
            prompt="Find customer with email 'customer@example.com'",
            browser_session_id=session_id,
            wait_for_completion=True,
        )

        print(f"Customer: {result.output}")

    finally:
        # Always close when done
        await client.close_browser_session(browser_session_id=session_id)

asyncio.run(main())

Run workflows with a session

Pass browser_session_id to run_workflow to execute a workflow in an existing session. This is useful when you need to run a predefined workflow but want it to continue from your current browser state.
import asyncio
from skyvern import Skyvern

async def main():
    client = Skyvern(api_key="YOUR_API_KEY")

    # Create session
    session = await client.create_browser_session(timeout=60)
    session_id = session.browser_session_id

    try:
        # First, login manually via a task
        await client.run_task(
            prompt="Login with username 'admin@company.com'",
            url="https://app.example.com/login",
            browser_session_id=session_id,
            wait_for_completion=True,
        )

        # Then run a workflow in the same session (already logged in)
        result = await client.run_workflow(
            workflow_id="wpid_export_monthly_report",
            browser_session_id=session_id,
            wait_for_completion=True,
        )

        print(f"Workflow completed: {result.status}")

    finally:
        await client.close_browser_session(browser_session_id=session_id)

asyncio.run(main())
You cannot use both browser_session_id and browser_profile_id in the same request. Choose one or the other.

Close a session

Close a session to release resources and stop billing. The browser shuts down immediately.
await client.close_browser_session(
    browser_session_id="pbs_490705123456789012"
)
Always close sessions when done. Active sessions continue billing even when idle. Use try/finally blocks to ensure cleanup.
try:
    session = await client.create_browser_session(timeout=30)
    session_id = session.browser_session_id

    # Do work...
    await client.run_task(
        prompt="...",
        browser_session_id=session_id,
        wait_for_completion=True,
    )

finally:
    # Always close, even if task fails
    await client.close_browser_session(browser_session_id=session_id)

Example: Human-in-the-loop

A shopping bot that pauses for human approval before completing a purchase.
import asyncio
from skyvern import Skyvern

async def shopping_with_approval():
    client = Skyvern(api_key="YOUR_API_KEY")

    session = await client.create_browser_session(timeout=15)
    session_id = session.browser_session_id

    try:
        # Step 1: Add to cart
        await client.run_task(
            prompt="Find wireless headphones under $100, add top result to cart",
            url="https://shop.example.com",
            browser_session_id=session_id,
            wait_for_completion=True,
        )

        # Step 2: Wait for human approval
        approval = input("Approve purchase? (yes/no): ")

        if approval.lower() == "yes":
            # Step 3: Checkout (cart persists from Step 1)
            result = await client.run_task(
                prompt="Complete checkout and confirm order",
                browser_session_id=session_id,
                wait_for_completion=True,
            )
            print(f"Order placed: {result.output}")
        else:
            print("Purchase cancelled")

    finally:
        await client.close_browser_session(browser_session_id=session_id)

asyncio.run(shopping_with_approval())
The browser maintains the cart contents during the approval pause. No state is lost.

Best practices

Set appropriate timeouts

Sessions bill while open, so match the timeout to your use case. A task typically completes in 30 to 90 seconds, so a 10-minute timeout covers most multi-step sequences with margin. Human-in-the-loop flows need longer timeouts to account for wait time.
# Quick multi-step task (2-3 tasks back to back)
session = await client.create_browser_session(timeout=10)

# Human-in-the-loop with wait time for approval
session = await client.create_browser_session(timeout=60)

# Long-running agent that monitors a dashboard
session = await client.create_browser_session(timeout=480)  # 8 hours

Use workflows for predetermined sequences

If your steps don’t need pauses between them, a workflow runs them in a single browser instance without the overhead of creating and managing a session. Each task in a session incurs its own startup cost, while workflow blocks share one browser.
# Less efficient: multiple tasks in a session (each task has startup overhead)
session = await client.create_browser_session()
await client.run_task(prompt="Step 1", browser_session_id=session.browser_session_id, wait_for_completion=True)
await client.run_task(prompt="Step 2", browser_session_id=session.browser_session_id, wait_for_completion=True)

# More efficient: single workflow (blocks share one browser, no inter-task overhead)
await client.run_workflow(workflow_id="wpid_abc", wait_for_completion=True)

Choose the right browser type

Chrome has the widest compatibility. Use Edge only when a site requires or detects it specifically.
# Chrome (default) - widest compatibility
session = await client.create_browser_session(browser_type="chrome")

# Edge - for sites that require or fingerprint Edge
session = await client.create_browser_session(browser_type="msedge")

Use extensions strategically

Extensions add startup time, so only enable them when needed. The ad-blocker removes overlay ads that can interfere with automation. The captcha-solver handles CAPTCHAs automatically but is only available on Cloud.
# Block ads that overlay content and interfere with clicks
session = await client.create_browser_session(extensions=["ad-blocker"])

# Auto-solve captchas (Cloud only)
session = await client.create_browser_session(extensions=["captcha-solver"])

Sessions vs Profiles

Skyvern also offers Browser Profiles, saved snapshots of browser state (cookies, storage, session files) that you can reuse across days or weeks. Choose based on your use case:
AspectBrowser SessionBrowser Profile
What it isLive browser instanceSaved snapshot of browser state
LifetimeMinutes to hoursDays to months
StateCurrent page, cookies, open connectionsCookies, storage, session files
BillingCharged while openNo cost when not in use
Best forBack-to-back tasks, human-in-the-loop, real-time agentsRepeated logins, scheduled workflows, shared auth state
You can create a Browser Profile from a completed session to save its authenticated state for future reuse.

Next steps

Connect Your Local Browser

Let Skyvern Cloud use your local browser with your existing logins

Browser Profiles

Save session state for reuse across days

Cost Control

Optimize costs with max_steps and efficient prompts