Skip to main content

Overview

Persistent Browser Sessions (PBS) allow you to maintain browser state across multiple tasks and workflow runs. This is essential for workflows that require maintaining login state, cookies, or other browser context between operations.

Key Benefits

  • State Persistence: Maintain login sessions, cookies, and local storage across tasks
  • Performance: Skip repeated authentication and navigation steps
  • Cost Efficiency: Reduce the number of steps and LLM calls by reusing authenticated sessions
  • Workflow Continuity: Chain multiple tasks together while preserving context

Browser Session Lifecycle

Browser sessions go through the following states:
class PersistentBrowserSessionStatus(StrEnum):
    created = "created"      # Session initialized
    running = "running"      # Session actively being used
    failed = "failed"        # Session encountered an error
    completed = "completed"  # Session finished successfully
    timeout = "timeout"      # Session exceeded timeout limit
    retry = "retry"          # Session is being retried

Creating a Browser Session

Via SDK (Python)

from skyvern import Skyvern

skyvern = Skyvern(api_key="your-api-key")

# Create a new browser session
browser = await skyvern.launch_cloud_browser()
page = await browser.get_working_page()

# Perform actions
await page.goto("https://example.com")
await page.agent.login(
    credential_type="skyvern",
    credential_id="cred_123"
)

# Get the session ID for reuse
session_id = browser.browser_session_id
print(f"Browser session: {session_id}")

# Keep browser open for reuse
# Don't call browser.close() if you want to reuse the session

Via SDK (TypeScript)

import { Skyvern } from "@skyvern/client";

const skyvern = new Skyvern({ apiKey: "your-api-key" });

// Create a new browser session
const browser = await skyvern.launchCloudBrowser();
const page = await browser.getWorkingPage();

// Perform actions
await page.goto("https://example.com");
await page.agent.login("skyvern", { credentialId: "cred_123" });

// Get the session ID for reuse
const sessionId = browser.browserSessionId;
console.log(`Browser session: ${sessionId}`);

Reusing Browser Sessions

Once you have a browser session ID, you can reuse it in subsequent tasks:

In Task Runs

from skyvern import Skyvern

skyvern = Skyvern(api_key="your-api-key")

# Reuse existing session
task = await skyvern.run_task(
    prompt="Navigate to account settings and update email",
    url="https://example.com/settings",
    browser_session_id="pbs_123456789"  # Reuse session
)

In Workflow Runs

workflow_run = await skyvern.run_workflow(
    workflow_id="wpid_123",
    parameters={"user_email": "[email protected]"},
    browser_session_id="pbs_123456789"  # Reuse session
)

Via API

curl -X POST https://api.skyvern.com/api/v1/tasks \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Check order status",
    "url": "https://example.com/orders",
    "browser_session_id": "pbs_123456789"
  }'

Session Configuration

Timeout Settings

Browser sessions have configurable timeout periods:
# Configure session timeout when creating
session = await skyvern.create_browser_session(
    timeout=45  # 45 minute timeout
)

Proxy and Geolocation

Browser sessions can be configured with specific proxy locations:
workflow_run = await skyvern.run_workflow(
    workflow_id="wpid_123",
    browser_session_id="pbs_123",
    proxy_location="RESIDENTIAL_GB"  # UK residential proxy
)

Managing Sessions

Listing Active Sessions

# Get all active browser sessions
sessions = await skyvern.get_browser_sessions()

for session in sessions:
    print(f"Session: {session.browser_session_id}")
    print(f"Status: {session.status}")
    print(f"Started: {session.started_at}")

Closing Sessions

# Close a specific session
await skyvern.close_browser_session("pbs_123456789")

# Or close via browser object
await browser.close()

Via CLI

# Create a session
skyvern browser session create --timeout 30

# List sessions
skyvern browser session list

# Get session details
skyvern browser session get pbs_123

# Close a session
skyvern browser session close pbs_123

Best Practices

Session Reuse Patterns

  1. Login Once, Use Many Times
# First task: Login and get session
browser = await skyvern.launch_cloud_browser()
page = await browser.get_working_page()
await page.goto("https://example.com")
await page.agent.login("skyvern", "cred_123")
session_id = browser.browser_session_id

# Subsequent tasks: Reuse session
for action in ["view_orders", "update_profile", "download_invoice"]:
    await skyvern.run_task(
        prompt=f"Perform {action}",
        browser_session_id=session_id
    )
  1. Multi-Step Workflows
# Step 1: Search and add to cart
task1 = await skyvern.run_task(
    prompt="Search for laptop and add to cart",
    url="https://store.com",
)

# Step 2: Checkout using same session
task2 = await skyvern.run_task(
    prompt="Complete checkout with saved payment",
    browser_session_id=task1.browser_session_id
)

Error Handling

from skyvern.exceptions import BrowserSessionNotRenewable

try:
    await skyvern.run_task(
        prompt="Check account",
        browser_session_id="pbs_old"
    )
except BrowserSessionNotRenewable:
    # Session expired, create new one
    browser = await skyvern.launch_cloud_browser()
    # Retry task with new session

Resource Management

# Always close sessions when done
try:
    browser = await skyvern.launch_cloud_browser()
    # ... perform tasks ...
finally:
    await browser.close()

Session Metadata

Browser sessions include compute and cost information:
session = await skyvern.get_browser_session("pbs_123")

print(f"Instance type: {session.instance_type}")
print(f"Duration: {session.duration_ms}ms")
print(f"Cost: ${session.compute_cost}")
print(f"Browser type: {session.browser_type}")  # chrome, msedge
print(f"IP address: {session.ip_address}")

Advanced: Custom Browser Connection

Connect to your own browser instance:
from skyvern import Skyvern

# Connect to local Chrome via CDP
skyvern = Skyvern(
    cdp_url="http://127.0.0.1:9222"
)

# Or specify Chrome path
skyvern = Skyvern(
    browser_path="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
)

task = await skyvern.run_task(
    prompt="Navigate and extract data",
    url="https://example.com"
)
Since Chrome 136, Chrome refuses CDP connections using the default user_data_dir. Skyvern automatically copies your default user_data_dir to ./tmp/user_data_dir the first time connecting to your local browser.

Troubleshooting

Session Not Found

If you get a session not found error, the session may have expired or been closed:
# Check if session exists and is active
try:
    session = await skyvern.get_browser_session("pbs_123")
    if session.status in ["completed", "failed", "timeout"]:
        # Create new session
        browser = await skyvern.launch_cloud_browser()
except NotFoundError:
    # Session doesn't exist
    browser = await skyvern.launch_cloud_browser()

Session Timeout

Increase timeout for long-running workflows:
session = await skyvern.create_browser_session(
    timeout=120  # 2 hour timeout
)

Build docs developers (and LLMs) love