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

# Extensions

> Upload a Chrome extension, load it in a browser session, and preserve its state when needed.

Upload an extension to your account, then pass its UUID when starting a browser. You can load up to five extensions in one session.

## Upload

Package an unpacked Chrome extension as a ZIP with `manifest.json` at the archive root. If you have a `.crx`, extract the extension files with a CRX-compatible tool before creating the ZIP.

```bash theme={null}
curl --fail-with-body "$SURFSKY_API_BASE_URL/extensions" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -F 'file=@my-extension.zip' \
  -F 'name=Reporting helper'
```

Save the top-level `uuid` from the response. Use the returned value as-is in subsequent requests.

## Use

Include `extensions` in a one-time or persistent-profile start request:

```json theme={null}
{ "extensions": ["EXTENSION_UUID"] }
```

The extension is loaded into the browser for that session. Check its permissions and configuration before using it against your target site.

## Manage

List the account's extensions:

```bash theme={null}
curl --fail-with-body "$SURFSKY_API_BASE_URL/extensions" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN"
```

Rename an extension with a JSON request:

```bash theme={null}
curl --fail-with-body -X PATCH "$SURFSKY_API_BASE_URL/extensions/EXTENSION_UUID" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name": "Updated reporting helper"}'
```

Delete an extension you no longer need:

```bash theme={null}
curl --fail-with-body -X DELETE "$SURFSKY_API_BASE_URL/extensions/EXTENSION_UUID" \
  -H "X-Cloud-Api-Token: $SURFSKY_API_TOKEN"
```

To update extension code, upload a new ZIP and use its new UUID on the next browser start. The rename endpoint does not replace an archive. Deleting an upload does not change the copy already loaded in a running browser.

## Persisting extension state

To retain extension data between sessions, enable extension storage when creating a persistent profile:

```json theme={null}
{
  "title": "my profile",
  "fingerprint": { "os": "win" },
  "storage_options": { "extensions": true }
}
```

Supply the extension UUIDs on each start. The storage option preserves extension state; it does not select which extensions to load.

## Limits and failure modes

| Error                     | Meaning                                                                                     |
| ------------------------- | ------------------------------------------------------------------------------------------- |
| `extension_limit_reached` | The account already has 100 uploaded extensions.                                            |
| `no_file_provided`        | The upload is missing a file.                                                               |
| `extension_upload_failed` | The archive could not be stored. Retry a temporary failure; contact support if it persists. |

If a page behaves differently with an extension loaded, compare the same workflow without it. Content scripts and request modifications can change both the page and the signals it observes. Use [DevTools](/debugging) to inspect those differences.
