Skip to main content

Overview

By default, browser state (cookies, localStorage, login sessions) is ephemeral and lost when the browser closes. Use --profile to persist state across browser restarts.

Quick Start

# Use a persistent profile directory
agent-browser --profile ~/.myapp-profile open myapp.com

# Login once, then reuse the authenticated session
agent-browser --profile ~/.myapp-profile open myapp.com/dashboard

# Or via environment variable
export AGENT_BROWSER_PROFILE=~/.myapp-profile
agent-browser open myapp.com

What Gets Stored

The profile directory stores all browser state that would normally be ephemeral:
  • Cookies - Session cookies, authentication tokens
  • localStorage - Client-side key-value storage
  • IndexedDB - Structured client-side databases
  • Service Workers - Background scripts and caches
  • Browser cache - Cached resources (images, scripts, stylesheets)
  • Login sessions - Persistent authentication state
  • Browser preferences - Settings and configurations
This is equivalent to Chrome’s user data directory (chrome://version → “Profile Path”).

Profile Directory Structure

Profiles use Playwright’s launchPersistentContext API (see src/browser.ts:1371-1387). The directory structure follows Chromium’s layout:
~/.myapp-profile/
├── Cache/
├── Code Cache/
├── Cookies
├── IndexedDB/
├── Local Storage/
├── Service Worker/
├── Session Storage/
└── Preferences

Path Expansion

Profile paths support tilde (~) expansion to your home directory:
# These are equivalent
agent-browser --profile ~/browser-profile open example.com
agent-browser --profile /home/user/browser-profile open example.com
Relative paths are resolved from the current working directory:
# Create profile in ./browser-data
agent-browser --profile ./browser-data open example.com

Multiple Profiles

Use different profile paths for different projects or accounts to keep their browser state isolated:
# Work account
agent-browser --profile ~/.profiles/work open mail.google.com

# Personal account
agent-browser --profile ~/.profiles/personal open mail.google.com

# Project-specific profile
agent-browser --profile ./project-browser open localhost:3000
Each profile has completely isolated state - cookies, logins, and storage are never shared between profiles.

Headless Mode with Profiles

Profiles work in both headed and headless mode:
# Headless (default) - state still persists
agent-browser --profile ~/.myapp-profile open myapp.com

# Headed - see the browser window
agent-browser --profile ~/.myapp-profile --headed open myapp.com

Profiles vs Session State

agent-browser provides two ways to persist state:
FeatureProfiles (--profile)Session State (--session-name)
Storage locationCustom directory~/.agent-browser/sessions/
What’s storedFull browser profileCookies + localStorage only
EncryptionNoYes (with AGENT_BROWSER_ENCRYPTION_KEY)
Browser lifecyclePersistent contextRegular context with state injection
Use caseFull browser stateLightweight auth persistence
Use profiles when:
  • You need full browser state (IndexedDB, service workers, cache)
  • You want complete isolation between projects
  • You’re running long-lived browser sessions
Use session state when:
  • You only need cookies and localStorage
  • You want encryption at rest
  • You want automatic state management

Compatibility

Limitations

Profiles have some restrictions due to how Playwright’s persistent contexts work: Cannot use with CDP connections:
# This will fail
agent-browser --profile ./profile --cdp 9222 open example.com
# Error: Profile cannot be used with CDP connection
Cannot use with storage state files:
# This will fail
agent-browser --profile ./profile --state ./state.json open example.com
# Error: Storage state cannot be used with profile (profile is already persistent storage)
See src/browser.ts:1204-1218 for the complete compatibility checks.

Extensions Support

Extensions require a persistent context, which is incompatible with user profiles:
# This will fail
agent-browser --profile ./profile --extension ./my-ext open example.com
# Error: Extensions cannot be used with profile
Extensions create their own temporary profile directory automatically (see src/browser.ts:1348-1370).

Security Considerations

Permissions

Profile directories contain sensitive data like cookies and auth tokens. Protect them with appropriate file permissions:
mkdir -p ~/.myapp-profile
chmod 700 ~/.myapp-profile

Sharing Profiles

Never commit profile directories to version control or share them between users. Each profile should be user-specific and machine-specific.

Multi-User Systems

On shared systems, use user-specific profile paths to prevent data leakage:
# Bad - shared location
agent-browser --profile /tmp/browser-profile open example.com

# Good - user-specific location
agent-browser --profile ~/.profiles/myapp open example.com

Cleanup

Profile directories can grow large over time due to browser cache. Clean them periodically:
# Remove cache but keep cookies/storage
rm -rf ~/.myapp-profile/Cache
rm -rf ~/.myapp-profile/Code\ Cache

# Complete reset (loses all state)
rm -rf ~/.myapp-profile

Use Cases

Authenticated Testing

Login once, then reuse the session for all tests:
# First run: login manually in headed mode
agent-browser --profile ./test-profile --headed open app.example.com
# (complete login flow interactively)

# Subsequent runs: headless with persistent auth
agent-browser --profile ./test-profile open app.example.com/dashboard
agent-browser --profile ./test-profile snapshot

Development Workflow

Maintain separate profiles for development vs production:
# Development profile
agent-browser --profile ./dev-profile open localhost:3000

# Production profile
agent-browser --profile ./prod-profile open app.example.com

Multi-Account Automation

Run multiple accounts simultaneously using different sessions:
# Account 1 in session "user1"
agent-browser --session user1 --profile ~/.profiles/user1 open app.com

# Account 2 in session "user2" (separate daemon instance)
agent-browser --session user2 --profile ~/.profiles/user2 open app.com
Each session gets its own daemon and browser instance, allowing true parallel execution.

Implementation Details

Profiles use Playwright’s launchPersistentContext API, which launches the browser with a permanent user data directory. This is the same mechanism Chrome uses for user profiles. From src/browser.ts:1371-1387:
const profilePath = options.profile!.replace(/^~\//, os.homedir() + '/');
context = await launcher.launchPersistentContext(profilePath, {
  headless: options.headless ?? true,
  executablePath: options.executablePath,
  args: baseArgs,
  viewport,
  extraHTTPHeaders: options.headers,
  userAgent: options.userAgent,
  ...(options.proxy && { proxy: options.proxy }),
  ignoreHTTPSErrors: options.ignoreHTTPSErrors ?? false,
  ...(this.colorScheme && { colorScheme: this.colorScheme }),
  ...(this.downloadPath && { downloadsPath: this.downloadPath }),
});
this.isPersistentContext = true;
The isPersistentContext flag is set to true, which affects how the browser is closed and how pages are managed throughout the session.

Build docs developers (and LLMs) love