> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Chrome Extension Module

> PraisonAI Chrome Extension for browser automation with multi-layer persistence

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Chrome Extension Module"
        Request[📋 User Request] --> Process[⚙️ Chrome Extension Module]
        Process --> Result[✅ Result]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Request input
    class Process process
    class Result output
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Feature as Chrome Extension Module

    User->>Agent: Request
    Agent->>Feature: Process request
    Feature-->>Agent: Result
    Agent-->>User: Response
```

# Chrome Extension

A Chrome Extension that enables AI-powered browser automation through the Chrome DevTools Protocol (CDP) with multi-layer persistence for reliable connections.

## Quick Start

<Steps>
  <Step title="Install">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    pip install praisonaiagents selenium
    ```
  </Step>

  <Step title="Create a browser automation agent">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    agent = Agent(
        name="BrowserAgent",
        instructions="Automate browser tasks and extract web content.",
    )

    agent.start("Navigate to example.com and extract the main heading")
    ```
  </Step>
</Steps>

## Architecture Overview

The extension uses a **multi-layer architecture** to ensure reliable browser automation:
The user asks for a browser task; the Chrome extension and agent automate the page via CDP.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "Chrome Extension"
        SW[Service Worker] 
        OD[Offscreen Document]
        CS[Content Scripts]
        SP[Side Panel]
    end
    
    subgraph "Bridge Layer"
        WS[WebSocket]
        BS[Bridge Server]
    end
    
    subgraph "PraisonAI"
        AG[AI Agent]
        CDP[CDP Engine]
    end
    
    OD -->|Layer 1: Primary| WS
    SW -->|Layer 2: Fallback| WS
    CS -->|Layer 3: Keep-Alive| SW
    WS --> BS
    BS --> AG
    AG --> CDP
    CDP -->|Direct Control| Chrome
    classDef tool fill:#189AB4,color:#fff
    classDef agent fill:#8B0000,color:#fff
```

## Multi-Layer Connection Strategy

Chrome Manifest V3 service workers terminate after 30 seconds of inactivity, which can kill WebSocket connections. We use a **three-layer approach** to maintain persistent connections:

### Layer 1: Offscreen Document (PRIMARY)

The offscreen document is the **primary** method for maintaining WebSocket connections:

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// Service worker creates offscreen document
await chrome.offscreen.createDocument({
    url: 'offscreen.html',
    reasons: [chrome.offscreen.Reason.BLOBS],
    justification: 'Persistent WebSocket connection for bridge server',
});
```

**Why Offscreen Document?**

* Lives longer than service workers
* Can maintain WebSocket connections indefinitely
* Auto-reconnects when bridge server restarts
* Sends heartbeats to keep connection alive

### Layer 2: Service Worker Bridge (FALLBACK)

If the offscreen document fails, the service worker maintains its own WebSocket:

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// Falls back to service worker bridge
bridgeClient = getBridgeClient({
    serverUrl: 'ws://localhost:8765/ws',
    maxReconnectAttempts: 3,
});
```

**When Used:**

* Offscreen document creation fails
* Chrome doesn't support offscreen API
* Temporary connection until offscreen is ready

### Layer 3: Content Script Keep-Alive (BACKUP)

Content scripts open persistent ports to keep the service worker alive:

```typescript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// Content script opens keep-alive port
const port = chrome.runtime.connect({ name: 'keepAlive' });

// Ping every 4.5 minutes (Chrome's 5-minute limit)
setInterval(() => port.postMessage({ type: 'ping' }), 270000);
```

## Internal Message Flow

When using extension mode, messages flow through multiple components:

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    CLI[Python CLI] -- "start_session" --> Bridge[Bridge Server :8765]
    Bridge -- "start_automation" --> Offscreen[Offscreen Document]
    Offscreen -- "OFFSCREEN_BRIDGE_MESSAGE" --> Background[Background Script]
    Background -- "handleMessage()" --> BridgeClient[bridgeClient]
    BridgeClient -- "onStartAutomation" --> Automation[Automation Loop]
    Automation -- "sendObservation()" --> BridgeClient
    BridgeClient -- "OFFSCREEN_SEND_BRIDGE" --> Offscreen
    Offscreen -- "WebSocket.send()" --> Bridge
    Bridge -- "action" --> Offscreen
```

### Message Types

| Message                    | Direction              | Purpose                               |
| -------------------------- | ---------------------- | ------------------------------------- |
| `start_session`            | CLI → Server           | Start automation with goal            |
| `start_automation`         | Server → Extension     | Trigger automation on extension       |
| `observation`              | Extension → Server     | Send page state to AI                 |
| `action`                   | Server → Extension     | AI-decided action to execute          |
| `OFFSCREEN_BRIDGE_MESSAGE` | Offscreen → Background | Forward server messages               |
| `OFFSCREEN_SEND_BRIDGE`    | Background → Offscreen | Send messages via offscreen WebSocket |

### Why This Architecture?

The offscreen document holds the **actual WebSocket connection** because:

* Service workers may terminate after 30s of inactivity
* Offscreen documents persist longer
* All outgoing messages route through offscreen

The background script's `bridgeClient` handles:

* Parsing incoming messages
* Calling appropriate handlers (e.g., `onStartAutomation`)
* Forwarding outgoing messages to offscreen

<Info>
  **Key Insight**: The `bridgeClient` in the background script doesn't have its own WebSocket. It routes all messages through the offscreen document's WebSocket connection.
</Info>

## Browser Automation Engines

### Extension Mode (PRIMARY)

Extension mode uses the WebSocket bridge for AI-driven browser automation:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai browser launch "search for AI" --engine extension
```

**How it works:**

1. Bridge server starts on `localhost:8765`
2. Chrome launches with extension loaded
3. Extension connects to bridge via WebSocket
4. AI agent sends actions, extension executes them

**Advantages:**

* ✅ Full browser context (cookies, sessions)
* ✅ Access to all tabs
* ✅ User-like interactions

### CDP Mode (FALLBACK)

CDP mode uses direct Chrome DevTools Protocol for reliable automation:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai browser launch "search for AI" --engine cdp
```

**How it works:**

1. Chrome launches with `--remote-debugging-port`
2. Python connects directly via CDP
3. No extension needed
4. Direct browser control

**Advantages:**

* ✅ Always reliable
* ✅ No extension required
* ✅ Faster for simple tasks

## Browser Subagent

The browser subagent is a **specialized AI agent** that handles browser interactions:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Browser subagent usage
result = browser_subagent(
    Task="Navigate to google.com and search for AI",
    TaskName="Google Search",
    RecordingName="search_demo"
)
```

### What Is It?

The browser subagent is a secondary agent with browser-specific tools:

* `click` - Click elements
* `type` - Enter text
* `navigate` - Go to URLs
* `scroll` - Scroll pages
* `screenshot` - Capture screenshots
* `wait` - Wait for elements

### How It's Used

1. **Main agent** delegates browser tasks to browser subagent
2. **Browser subagent** uses CDP to control Chrome
3. **Results** returned to main agent

### Is It a Fallback?

**No** - The browser subagent is the **main agent** for browser control. It's used by both:

* Extension mode (via WebSocket bridge)
* CDP mode (direct control)

## Technology Stack

| Component     | Technology              | Purpose                     |
| ------------- | ----------------------- | --------------------------- |
| Extension     | Chrome Manifest V3      | Browser integration         |
| Persistence   | Offscreen Document API  | Long-lived WebSocket        |
| Communication | WebSocket               | Real-time bidirectional     |
| Control       | CDP (DevTools Protocol) | Direct browser manipulation |
| AI            | PraisonAI Agent         | Decision making             |

## Project Structure

```
praisonai-chrome-extension/
├── src/
│   ├── background/     # Service worker (Layer 2)
│   │   └── index.ts    # Bridge connection, CDP, agents
│   ├── offscreen/      # Offscreen document (Layer 1)
│   │   └── index.ts    # Persistent WebSocket
│   ├── content/        # Content scripts (Layer 3)
│   │   └── index.ts    # Keep-alive ports
│   ├── sidepanel/      # Side panel UI
│   ├── cdp/            # CDP client library
│   ├── bridge/         # WebSocket bridge client
│   └── ai/             # AI modules (Gemini Nano)
├── dist/               # Built extension
└── manifest.json       # Extension manifest
```

## Installation

### From Source

1. Clone and build:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
git clone https://github.com/MervinPraison/praisonai-chrome-extension.git
cd praisonai-chrome-extension
npm install
npm run build
```

2. Load in Chrome:
   * Open `chrome://extensions`
   * Enable "Developer mode"
   * Click "Load unpacked"
   * Select the `dist` folder

### Via CLI

The CLI automatically loads the extension:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai browser launch "search for AI" --engine extension
```

## Manual Load Recovery (Chrome 137+ / Windows)

The CLI's auto-load can silently fail on **Chrome 137+ / Windows**, which blocks automated `--load-extension`. When that happens, `launch` prints a manual "Load unpacked" flow — load the extension into your daily "Work" Chrome instead.

<Steps>
  <Step title="Open chrome://extensions">
    Use your normal Chrome (Work profile) and enable **Developer mode**.
  </Step>

  <Step title="Load unpacked">
    Click **Load unpacked** and select the `dist/` folder.
  </Step>

  <Step title="Verify the connection">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai browser doctor extension
    # expect: ✅ Extension connected to bridge (1 connection(s))
    ```
  </Step>
</Steps>

<Note>
  If you launched with `--no-server`, start the bridge first (`praisonai browser start`), then re-run `praisonai browser doctor extension`. See the full flow in [Manual Extension Load](/docs/features/browser-agent-deep-dive#manual-extension-load-chrome-137-windows).
</Note>

## Keyboard Shortcuts

| Shortcut       | Action             |
| -------------- | ------------------ |
| `Ctrl+Shift+P` | Toggle side panel  |
| `Alt+A`        | Start agent        |
| `Alt+S`        | Capture screenshot |

Mac users: Use `Cmd` instead of `Ctrl`

## Configuration

```javascript theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
// Extension settings (storage.local)
{
    "bridgeServerUrl": "ws://localhost:8765/ws",
    "preferBridge": true,
    "fallbackToBuiltIn": true,
    "maxSteps": 20
}
```

## Profile Persistence

By default, PraisonAI uses a **persistent Chrome profile** at `~/.praisonai/browser_profile`. This provides:

* ✅ **Consistent Extension ID**: Same ID across runs for reliable automation
* ✅ **Session Persistence**: Cookies, login state, and history preserved
* ✅ **Faster Startup**: No need to re-initialize extension settings

### Default Behavior (Persistent)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Uses ~/.praisonai/browser_profile by default
praisonai browser launch "search for AI" --engine extension
```

### Custom Profile Path

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Use a custom profile directory
praisonai browser launch "search for AI" --chrome-profile /path/to/profile
```

### Temporary Profile

For isolated testing or clean sessions, use `--temp-profile`:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Uses a temporary profile (deleted after run)
praisonai browser launch "search for AI" --temp-profile
```

<Warning>
  **Chrome 137+ Note**: The `--load-extension` flag will be removed in Chrome 137 (June 2025) for branded Chrome. For continued automation, use:

  * **Chromium** (open-source)
  * **Chrome for Testing** (automation-optimized)
</Warning>

## Troubleshooting

### Extension Not Connecting

If you see "Timeout after 30s" errors:

1. **Check bridge server:**
   ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
   curl http://localhost:8765/health
   ```

2. **Check extension console:**
   * Go to `chrome://extensions`
   * Find "PraisonAI Browser Agent"
   * Click "Inspect views: service worker"
   * Look for connection errors

3. **Use CDP fallback:**
   ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
   praisonai browser launch "search for AI" --engine cdp
   ```

### CLI says "No automation steps in 30s"

The `praisonai browser run` first-step watchdog fired because `start_automation` was not confirmed delivered to an extension. Verify the bridge sees an extension and that no other client holds it:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
curl http://127.0.0.1:8765/health    # expect extension_connections >= 1
```

Use the side panel **or** the CLI, not both at once. For extension-free automation, add `--engine cdp`.

### "Receiving End Does Not Exist" Error

This occurs when the offscreen document isn't ready. The extension now:

* Waits 1 second after creating offscreen document
* Retries 3 times with 500ms delay
* Falls back to service worker bridge

### Chrome Instance Management

The CLI only manages its own Chrome instance:

* ✅ Only kills the Chrome window it launched
* ✅ Does NOT kill your manually opened Chrome windows
* ✅ Reuses existing session when possible

## Permissions

The extension requires:

| Permission   | Purpose                   |
| ------------ | ------------------------- |
| `debugger`   | CDP access for automation |
| `offscreen`  | Persistent WebSocket      |
| `activeTab`  | Current tab interaction   |
| `storage`    | Settings persistence      |
| `sidePanel`  | Side panel UI             |
| `<all_urls>` | Page interaction          |

## Development

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
npm run dev      # Development build with watch
npm run build    # Production build
npm run test     # Run tests
npm run lint     # Check code style
```

## Best Practices

<AccordionGroup>
  <Accordion title="Use for browser automation">
    The Chrome extension is ideal for sites that require login or render content with JavaScript.
  </Accordion>

  <Accordion title="Handle authentication flows">
    The extension preserves browser session cookies - use it for sites requiring authentication.
  </Accordion>

  <Accordion title="Minimize extension permissions">
    Request only the browser permissions your automation needs to reduce security risk.
  </Accordion>

  <Accordion title="Test in headless mode">
    Run in headless mode for CI/CD pipelines and server-side automation without a display.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Custom Tools" icon="wrench" href="/docs/tools/custom">
    Build your own agent tools
  </Card>

  <Card title="Tools Overview" icon="toolbox" href="/docs/tools/tools">
    Browse PraisonAI tool documentation
  </Card>
</CardGroup>
