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

# Browser Extensions

> Load custom Chrome extensions into your browser sessions

Load your own custom Chrome extensions into Hyperbrowser sessions to add custom functionality, developer tools, or automation capabilities.

<Warning>
  Hyperbrowser officially supports custom chrome extensions. Extensions from the Chrome webstore may work, but our ability to provide support regarding those would be limited. You must first upload your extension as a `.zip` file before using it in sessions.
</Warning>

## Upload Your Extension

Before using an extension in a session, you must upload it to Hyperbrowser.

### Step 1: Package Your Extension

Package your Chrome extension as a `.zip` file with the standard Chrome extension structure:

```
my-extension/
├── manifest.json
├── background.js
├── content.js
└── icons/
    └── icon.png
```

**Example manifest.json:**

```json theme={null}
{
  "manifest_version": 3,
  "name": "My Custom Extension",
  "version": "1.0",
  "description": "Custom extension for automation",
  "permissions": ["storage", "tabs"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}
```

<Tip>
  Ensure your `manifest.json` is at the root level of the `.zip` file, not inside a subdirectory. You should zip the contents of the extension directory, not the directory itself.
</Tip>

### Step 2: Upload to Hyperbrowser

<CodeGroup>
  ```typescript Node.js theme={null}
  import { Hyperbrowser } from "@hyperbrowser/sdk";

  const client = new Hyperbrowser({
    apiKey: process.env.HYPERBROWSER_API_KEY,
  });

  // Upload extension (.zip file)
  const extension = await client.extensions.create({
    filePath: "/path/to/extension.zip",
    name: "My Custom Extension",  // optional
  });

  console.log("Extension uploaded:", extension.id);
  console.log("Extension name:", extension.name);
  ```

  ```python Python theme={null}
  import os
  from hyperbrowser import Hyperbrowser
  from hyperbrowser.models import CreateExtensionParams

  client = Hyperbrowser(api_key=os.getenv("HYPERBROWSER_API_KEY"))

  # Upload extension (.zip file)
  extension = client.extensions.create(
      CreateExtensionParams(
          file_path="/path/to/extension.zip",
          name="My Custom Extension",  # optional
      )
  )

  print(f"Extension uploaded: {extension.id}")
  print(f"Extension name: {extension.name}")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/extensions/add \
    -H "x-api-key: YOUR_API_KEY" \
    -F "file=@/path/to/extension.zip" \
    -F "name=My Custom Extension"
  ```
</CodeGroup>

## Use Extensions in Sessions

Once uploaded, load your extension(s) when creating a session:

<CodeGroup>
  ```typescript Node.js theme={null}
  import { Hyperbrowser } from "@hyperbrowser/sdk";

  const client = new Hyperbrowser({
    apiKey: process.env.HYPERBROWSER_API_KEY,
  });

  // Create session with your uploaded extension
  const session = await client.sessions.create({
    extensionIds: [
      "extension-id-from-upload-step",
    ],
  });

  console.log("Session created:", session.id);
  console.log("Extension loaded successfully");
  ```

  ```python Python theme={null}
  from hyperbrowser import Hyperbrowser
  from hyperbrowser.models import CreateSessionParams
  import os

  client = Hyperbrowser(api_key=os.getenv("HYPERBROWSER_API_KEY"))

  # Create session with your uploaded extension
  session = client.sessions.create(
      params=CreateSessionParams(
          extension_ids=[
              "extension-id-from-upload-step"
          ]
      )
  )

  print(f"Session created: {session.id}")
  print(f"Extension loaded successfully")
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/session \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "extensionIds": ["extension-id-from-upload-step"]
    }'
  ```
</CodeGroup>

## Managing Extensions

### List Your Extensions

View all uploaded extensions:

<CodeGroup>
  ```typescript Node.js theme={null}
  const extensions = await client.extensions.list();

  console.log(extensions)
  ```

  ```python Python theme={null}
  extensions = client.extensions.list()

  print(extensions)
  ```

  ```bash cURL theme={null}
  curl -X GET https://api.hyperbrowser.ai/api/extensions/list \
    -H "x-api-key: YOUR_API_KEY"
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Test locally first" icon="flask">
    Always test your extension in a local Chrome browser before uploading to Hyperbrowser. This helps catch manifest errors and permission issues early.
  </Accordion>

  <Accordion title="Minimize extension size" icon="compress">
    Keep extensions lightweight. Remove unnecessary files and compress images to reduce upload time and session startup overhead.
  </Accordion>

  <Accordion title="Use manifest v3" icon="file-code">
    Use Manifest V3 for better compatibility and performance. Chrome is phasing out Manifest V2.
  </Accordion>

  <Accordion title="Limit extensions per session" icon="gauge">
    Only load extensions you actually need. Each extension adds memory overhead and startup time.
  </Accordion>
</AccordionGroup>

## Troubleshooting

### Extension Not Loading

If your extension doesn't load:

1. **Verify the .zip structure** - Ensure `manifest.json` is at the root level, not in a subdirectory
2. **Check manifest validity** - Validate your `manifest.json` against Chrome extension standards
3. **Test locally first** - Load the extension in Chrome (chrome://extensions) to verify it works
4. **Check file size** - Very large extensions may fail to upload
5. **Review permissions** - Ensure your manifest includes all necessary permissions

### Extension Not Working

If the extension loads but doesn't function:

1. **Check console logs** - Use Live View to see browser console errors
2. **Verify content script matching** - Ensure your `matches` patterns are correct in manifest
3. **Test permissions** - Some APIs require specific permissions in manifest
4. **Check timing** - Extension scripts may need time to initialize before your automation runs

### Upload Failures

If upload fails:

1. **Verify file format** - Must be a `.zip` file
2. **Check file size** - Keep extensions under 8MB
3. **Ensure valid manifest** - Invalid `manifest.json` will cause upload to fail
4. **Remove unnecessary files** - Delete source maps, tests, or development files

## Limitations

<Warning>
  **Current Limitations:**

  * Extensions must be uploaded as `.zip` files
  * Extensions must be compatible with Chrome/Chromium
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Downloads" icon="download" href="/sessions/downloads">
    Handle file downloads in sessions
  </Card>

  <Card title="Profiles" icon="user" href="/sessions/profiles">
    Persist extension settings across sessions
  </Card>

  <Card title="Live View" icon="eye" href="/sessions/live-view">
    Watch extensions in action
  </Card>

  <Card title="Stealth Mode" icon="user-secret" href="/sessions/stealth">
    Combine with anti-detection features
  </Card>
</CardGroup>
