# Table of Contents
- [Kameleo Developer Center](#kameleo-developer-center)
- [Installation | Kameleo Developer Center](#installation-kameleo-developer-center)
- [Quickstart | Kameleo Developer Center](#quickstart-kameleo-developer-center)
- [Fingerprints | Kameleo Developer Center](#fingerprints-kameleo-developer-center)
- [Configure | Kameleo Developer Center](#configure-kameleo-developer-center)
- [Troubleshooting | Kameleo Developer Center](#troubleshooting-kameleo-developer-center)
- [Docker | Kameleo Developer Center](#docker-kameleo-developer-center)
- [Profiles | Kameleo Developer Center](#profiles-kameleo-developer-center)
- [Playwright | Kameleo Developer Center](#playwright-kameleo-developer-center)
- [Kernels | Kameleo Developer Center](#kernels-kameleo-developer-center)
- [Filter browser fingerprints | Kameleo Developer Center](#filter-browser-fingerprints-kameleo-developer-center)
- [Teamwork | Kameleo Developer Center](#teamwork-kameleo-developer-center)
- [Selenium | Kameleo Developer Center](#selenium-kameleo-developer-center)
- [Puppeteer | Kameleo Developer Center](#puppeteer-kameleo-developer-center)
- [Import & export cookies | Kameleo Developer Center](#import-export-cookies-kameleo-developer-center)
- [Pass command-line switches | Kameleo Developer Center](#pass-command-line-switches-kameleo-developer-center)
- [Emulate mobile devices | Kameleo Developer Center](#emulate-mobile-devices-kameleo-developer-center)
- [Manage profiles | Kameleo Developer Center](#manage-profiles-kameleo-developer-center)
- [Using proxy servers | Kameleo Developer Center](#using-proxy-servers-kameleo-developer-center)
- [Install browser extensions | Kameleo Developer Center](#install-browser-extensions-kameleo-developer-center)
- [Start headless browsers | Kameleo Developer Center](#start-headless-browsers-kameleo-developer-center)
- [Usage limits | Kameleo Developer Center](#usage-limits-kameleo-developer-center)
- [Disable closed shadow DOMs | Kameleo Developer Center](#disable-closed-shadow-doms-kameleo-developer-center)
- [Code examples | Kameleo Developer Center](#code-examples-kameleo-developer-center)
- [Architecture overview | Kameleo Developer Center](#architecture-overview-kameleo-developer-center)
- [Configuration options | Kameleo Developer Center](#configuration-options-kameleo-developer-center)
- [API error handling | Kameleo Developer Center](#api-error-handling-kameleo-developer-center)
- [Blacklisted browser switches | Kameleo Developer Center](#blacklisted-browser-switches-kameleo-developer-center)
- [Engine exit codes | Kameleo Developer Center](#engine-exit-codes-kameleo-developer-center)
- [Performance benchmark | Kameleo Developer Center](#performance-benchmark-kameleo-developer-center)
- [API reference | Kameleo Developer Center](#api-reference-kameleo-developer-center)
- [Using Fingerprint Inspector | Kameleo Developer Center](#using-fingerprint-inspector-kameleo-developer-center)
- [Unknown](#unknown)
---
# Kameleo Developer Center
Welcome to Kameleo Developer Center
Copy
===============================================

Tired of configurations that work for 2 hours before getting blocked? Automate browsers at scale and stay undetected. Scrape anti-bot protected websites through your favorite automation framework.
Sound familiar?
---------------
* "My success rate dropped to 10% overnight."
* "I patched CDP, fixed canvas, handled WebGL... still blocked."
* "I've tried multiple anti-detect browsers – none work consistently."
You're not the problem. Your tools are. Kameleo adapts regularly to anti-bot changes, delivering always-current fingerprints so your browser operations look like ordinary human traffic – and you can focus on your product, not the arms race.
What you get
------------
#### Fingerprints that stay fresh
When Chrome and Firefox update, we update. Automatically. Our browser kernels ship with continuously updated, authentic fingerprints.
#### No more stealth plugin Frankenstein
Canvas, WebGL, CDP, timezone, geolocation, fonts – all handled out-of-the-box. No extra plugins to maintain.
#### One tool for all targets
Run Chroma and Junglefox side-by-side for maximum diversity. Stop switching tools per domain.
#### Working code in 5 minutes
Use Kameleo SDKs (Python, JavaScript, C#) to control browsers directly with Selenium, Puppeteer, or Playwright. Copy, paste, run.
#### Long-lived profiles, no relogins
Keep cookies, local storage, and extensions across sessions easily. Profiles persist so your accounts don't get flagged for behavioral anomalies.
#### Performance & uptime
99.99% uptime with lightning-fast profile startup for smooth scaling.
Built to grow with you
----------------------
Works at 5 profiles. Works at 500. Predictable concurrency-based pricing means you know exactly what you'll pay – no "what counts as an API call?" confusion. Create unlimited profiles, invite unlimited team members, and deploy to Docker when you're ready for cloud-native infrastructure.
Up and running in minutes
-------------------------
1. **Install** – Simple to install using a package manager.
2. **Run the quickstart** – Copy our Python/JS/C# example.
3. **Watch it work** – Launch a profile, connect Selenium/Puppeteer/Playwright, see the difference.
Head to the [Installation](https://developer.kameleo.io/getting-started/installation/)
guide, then finish the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
to launch and automate your first profile.
Community & support
-------------------
* Discord: [Join Kameleo Insider](https://discord.com/invite/vNqxWuDkS4)
* Telegram: [Subscribe to our channel](https://t.me/kameleoapp)
* Help Center: [https://help.kameleo.io/](https://help.kameleo.io/)
* SDK repos & example codes: [https://github.com/kameleo-io/kameleo](https://github.com/kameleo-io/kameleo)
[On this page](https://developer.kameleo.io/)
* [Sound familiar?](https://developer.kameleo.io/#sound-familiar)
* [What you get](https://developer.kameleo.io/#what-you-get)
* [Fingerprints that stay fresh](https://developer.kameleo.io/#fingerprints-that-stay-fresh)
* [No more stealth plugin Frankenstein](https://developer.kameleo.io/#no-more-stealth-plugin-frankenstein)
* [One tool for all targets](https://developer.kameleo.io/#one-tool-for-all-targets)
* [Working code in 5 minutes](https://developer.kameleo.io/#working-code-in-5-minutes)
* [Long-lived profiles, no relogins](https://developer.kameleo.io/#long-lived-profiles-no-relogins)
* [Performance & uptime](https://developer.kameleo.io/#performance--uptime)
* [Built to grow with you](https://developer.kameleo.io/#built-to-grow-with-you)
* [Up and running in minutes](https://developer.kameleo.io/#up-and-running-in-minutes)
* [Community & support](https://developer.kameleo.io/#community--support)
⌘K
---
# Installation | Kameleo Developer Center
Installation
Copy
========================
This page walks you through installing Kameleo, starting the Local API, adding an SDK, and confirming the service is reachable. After finishing, you can run headless or with GUI and move on to the Quickstart.
1\. System requirements
-----------------------
| Component | Minimum | Recommended |
| --- | --- | --- |
| OS | Windows 10+, Windows Server 2016+
macOS 12+ (Apple Silicon)
Docker (Linux or Windows container) | Latest stable OS version |
| RAM | 4 GB | 8+ GB for multi-profile automation |
| Disk | 5 GB free | 20+ GB (to cache multiple kernels & profiles) |
| Network | Stable broadband | Low‑latency connection for high concurrency |
2\. Download & install
----------------------
[Windows (Installer)](https://developer.kameleo.io/getting-started/installation/#windows-installer)
[Windows (Winget)](https://developer.kameleo.io/getting-started/installation/#windows-winget)
[macOS (Installer)](https://developer.kameleo.io/getting-started/installation/#macos-installer)
[macOS (Homebrew Cask)](https://developer.kameleo.io/getting-started/installation/#macos-homebrew-cask)
[Docker](https://developer.kameleo.io/getting-started/installation/#docker)
1. Visit [kameleo.io/downloads](https://kameleo.io/downloads)
2. Download the Windows installer and run it.
3. Launch Kameleo Desktop once to verify installation.
3\. Start the Engine (headless or with GUI)
-------------------------------------------
Launching the Desktop app also starts the Engine in the background. For headless automation-only usage run the Engine binary directly:
[Windows](https://developer.kameleo.io/getting-started/installation/#windows)
[macOS](https://developer.kameleo.io/getting-started/installation/#macos)
[Docker](https://developer.kameleo.io/getting-started/installation/#docker-1)
`& "$Env:LOCALAPPDATA\Programs\Kameleo\Kameleo.Engine.exe" pat=`
##### Note
The `pat` (Personal Access Token) argument is optional. If omitted, the Engine starts in accountless mode. See [Configuration options](https://developer.kameleo.io/reference/configuration-options/)
for details.
The Engine listens on `http://localhost:5050` by default.
4\. Change configuration (optional)
-----------------------------------
Adjust listening host/port, credential, workspace paths, and logging level if the defaults don't meet your needs. See [Configure](https://developer.kameleo.io/getting-started/configure/)
for a guided setup and [Configuration options](https://developer.kameleo.io/reference/configuration-options/)
for the complete key list and defaults.
5\. Verify
----------
Visit [http://localhost:5050/swagger](http://localhost:5050/swagger)
while the Engine runs. If it loads, the Local API is ready. Follow the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
to launch and automate your first profile.
[On this page](https://developer.kameleo.io/getting-started/installation/)
* [1\. System requirements](https://developer.kameleo.io/getting-started/installation/#1-system-requirements)
* [2\. Download & install](https://developer.kameleo.io/getting-started/installation/#2-download--install)
* [3\. Start the Engine (headless or with GUI)](https://developer.kameleo.io/getting-started/installation/#3-start-the-engine-headless-or-with-gui)
* [4\. Change configuration (optional)](https://developer.kameleo.io/getting-started/installation/#4-change-configuration-optional)
* [5\. Verify](https://developer.kameleo.io/getting-started/installation/#5-verify)
⌘K
---
# Quickstart | Kameleo Developer Center
Quickstart
Copy
======================
Learn how to spin up the local Kameleo Engine, connect via an SDK, search a fingerprint, then create, start, automate, and stop a reusable profile. Core automation examples (Selenium, Puppeteer, Playwright) show how to drive the running profile immediately.
##### Note
API usage is subject to requests-per-minute limits. See the detailed limits table in [Usage limits](https://developer.kameleo.io/reference/usage-limits/)
.
1\. Start the Kameleo Engine
----------------------------
Ensure the Kameleo Engine is installed and running (see [Installation](https://developer.kameleo.io/getting-started/installation/)
). When started locally, it serves its API at [http://localhost:5050](http://localhost:5050/)
by default.
2\. Install an SDK
------------------
Kameleo components and SDKs follow semantic versioning (_major_._minor_._patch_). For the most reliable experience, install SDK versions whose _major_ and _minor_ match your running Kameleo Engine version.
##### Version compatibility
Using a significantly newer SDK with an older Engine (or vice versa) can result in missing operations, model field mismatches, or unexpected errors.
Select one of the language SDKs below to get started:
[Python](https://developer.kameleo.io/getting-started/quickstart/#python)
[JavaScript](https://developer.kameleo.io/getting-started/quickstart/#javascript)
[C#](https://developer.kameleo.io/getting-started/quickstart/#c)
`pip install kameleo.local-api-client`
For more details see our package at [PyPI.org](https://pypi.org/project/kameleo-local-api-client/)
.
3\. Create a client
-------------------
Create a client instance pointed at the local endpoint. All SDKs expose the same operations.
[Python](https://developer.kameleo.io/getting-started/quickstart/#python-1)
[JavaScript](https://developer.kameleo.io/getting-started/quickstart/#javascript-1)
[C#](https://developer.kameleo.io/getting-started/quickstart/#c-1)
`from kameleo.local_api_client import KameleoLocalApiClient client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready()`
4\. Search a fingerprint
------------------------
Search for a fingerprint matching the desired device type, operating system, browser, and version. You can filter versions with operators like >, >=, or <. Each result set returns a maximum of 25 fingerprints, ordered by browser version in descending order.
[Python](https://developer.kameleo.io/getting-started/quickstart/#python-2)
[JavaScript](https://developer.kameleo.io/getting-started/quickstart/#javascript-2)
[C#](https://developer.kameleo.io/getting-started/quickstart/#c-2)
`fps = client.fingerprint.search_fingerprints( device_type='desktop', os_family='windows', browser_product='chrome', browser_version='>145', )`
5\. Create profile
------------------
Create a profile from that fingerprint with a given name. Proxy, storage settings and other options are optional and skipped here.
[Python](https://developer.kameleo.io/getting-started/quickstart/#python-3)
[JavaScript](https://developer.kameleo.io/getting-started/quickstart/#javascript-3)
[C#](https://developer.kameleo.io/getting-started/quickstart/#c-3)
`from kameleo.local_api_client.models import CreateProfileRequest profile = client.profile.create_profile(CreateProfileRequest(fingerprint_id=fps[0].id, name='quick demo'))`
6\. Start profile
-----------------
Start the profile. Missing kernel files download automatically and a browser opens for automation.
[Python](https://developer.kameleo.io/getting-started/quickstart/#python-4)
[JavaScript](https://developer.kameleo.io/getting-started/quickstart/#javascript-4)
[C#](https://developer.kameleo.io/getting-started/quickstart/#c-4)
`client.profile.start_profile(profile.id)`
Next steps
----------
Continue by automating the running profile using one of these guides:
* [Selenium integration guide](https://developer.kameleo.io/integrations/selenium/)
* [Playwright integration guide](https://developer.kameleo.io/integrations/playwright/)
* [Puppeteer integration guide](https://developer.kameleo.io/integrations/puppeteer/)
[On this page](https://developer.kameleo.io/getting-started/quickstart/)
* [1\. Start the Kameleo Engine](https://developer.kameleo.io/getting-started/quickstart/#1-start-the-kameleo-engine)
* [2\. Install an SDK](https://developer.kameleo.io/getting-started/quickstart/#2-install-an-sdk)
* [3\. Create a client](https://developer.kameleo.io/getting-started/quickstart/#3-create-a-client)
* [4\. Search a fingerprint](https://developer.kameleo.io/getting-started/quickstart/#4-search-a-fingerprint)
* [5\. Create profile](https://developer.kameleo.io/getting-started/quickstart/#5-create-profile)
* [6\. Start profile](https://developer.kameleo.io/getting-started/quickstart/#6-start-profile)
* [Next steps](https://developer.kameleo.io/getting-started/quickstart/#next-steps)
⌘K
---
# Fingerprints | Kameleo Developer Center
Fingerprints
Copy
========================
A fingerprint is a real set of browser and device details (like user agent, OS, screen, GPU, languages) collected from an actual machine. Kameleo uses it to create a virtual browser profile whose values naturally belong together, instead of random mixes that look fake. Most fields come directly from the real sample; only a few dynamic parts are generated at creation to keep each profile unique. You can search through hundreds of thousands of fingerprints and filter by device type, platform, browser (and version), and language to quickly find the one you need.
What a fingerprint includes
---------------------------
A fingerprint encapsulates a coherent set of attributes sourced from real telemetry and curated datasets:
* User agent (including build & patch numbers) aligned with kernel capabilities
* Platform & OS metadata (e.g., Windows 11 64-bit, macOS 14, Android 14)
* Hardware exposure: device memory tiers, logical processor count buckets
* Rendering surfaces: WebGL vendor/renderer pairs, canvas entropy seeds
* Locale & languages (Accept-Language, navigator.language, time zone offset range)
* Screen & window metrics (resolution, color depth, pixel ratio)
* Media capabilities (audio/video codecs advertised via MSE / WebRTC)
* Browser feature switches / UA client hints (for versions that use them)
Kameleo rehydrates this data into a running profile and fills any intentionally mutable fields (like some WebRTC ICE candidates or WebGL noise) at profile creation time to maintain uniqueness.
Why fingerprints matter
-----------------------
If you just randomize values you often end up with impossible mixes (like a GPU that never ships with that CPU, or a user agent claiming features that browser build doesn’t have). Detection systems notice these mismatches and lower trust. Real fingerprints keep related values in sync, so there are fewer red flags. That’s why Kameleo doesn’t let you manually change tightly linked fields like the user agent by itself - changing one piece would break the natural consistency and make the profile look fake.
Filtering strategy
------------------
When searching fingerprints you can specify:
| Parameter | Example | Notes |
| --- | --- | --- |
| deviceType | `desktop`, `mobile` | Impacts available screen sizes & input emulation |
| platform | `windows`, `macos`, `ios`, `android` | Maps to kernel and emulation mode |
| browserProduct | `chrome`, `edge`, `firefox`, `safari` | Safari/iOS Safari emulate via Chroma mobile mode |
| browserVersion | `>145`, `=146` | Semantic comparator operators supported |
| language | `en-US`, `de`, `de-DE,de,en` | Sets Accept-Language & navigator.language(s) |
Example:
[Python](https://developer.kameleo.io/concepts/fingerprints/#python)
[JavaScript](https://developer.kameleo.io/concepts/fingerprints/#javascript)
[C#](https://developer.kameleo.io/concepts/fingerprints/#c)
`fps = client.fingerprint.search_fingerprints( device_type='desktop', os_family='windows', browser_product='chrome', browser_version='>145', )`
Version alignment
-----------------
Kernel versions are selected to match (or closely bracket) the fingerprint's browser version. If an exact build is unavailable, Kameleo chooses the nearest patched kernel ensuring feature parity without leaking mismatch signals.
Reuse vs. rotation
------------------
Reuse a fingerprint when you want to keep a stable, long‑lived account or session identity. It is more efficient because you skip an extra fingerprint lookup and you keep behavioral and technical signals consistent over time. Even if you start multiple profiles from the same fingerprint at different moments, Kameleo still produces unique profiles: transient or noise fields (like some WebRTC candidates, canvas noise, minor entropy seeds) are freshly generated each time so they are not perfect clones.
Rotate (pick a different fingerprint) when you need a clearly separate identity: for parallel account farming, A/B testing isolated personas, or when a site starts assigning risk to the current profile. Avoid rotating too often without a reason - rapid unexplained changes in hardware/browser traits can itself look suspicious.
Limitations
-----------
* Safari/WebKit fingerprints are emulated through Chroma's mobile emulation; certain WebKit-only APIs may not be identical.
* Rare legacy browsers are intentionally excluded to avoid improbable fingerprints.
Best practices
--------------
* Align proxy geo with the fingerprint's locale/time zone for higher trust.
* Prefer mainstream, broadly deployed browser versions (current stable ± a few) over bleeding-edge or trailing versions.
* Let Kameleo manage user agent and platform fields; avoid overwriting them via automation scripts or page injections.
* Use realistic locale + time zone pairs (e.g., en-US + US zone); avoid improbable mixes.
Keep window/screen sizes within typical ranges for the device type; avoid exotic resolutions.
[On this page](https://developer.kameleo.io/concepts/fingerprints/)
* [What a fingerprint includes](https://developer.kameleo.io/concepts/fingerprints/#what-a-fingerprint-includes)
* [Why fingerprints matter](https://developer.kameleo.io/concepts/fingerprints/#why-fingerprints-matter)
* [Filtering strategy](https://developer.kameleo.io/concepts/fingerprints/#filtering-strategy)
* [Version alignment](https://developer.kameleo.io/concepts/fingerprints/#version-alignment)
* [Reuse vs. rotation](https://developer.kameleo.io/concepts/fingerprints/#reuse-vs-rotation)
* [Limitations](https://developer.kameleo.io/concepts/fingerprints/#limitations)
* [Best practices](https://developer.kameleo.io/concepts/fingerprints/#best-practices)
⌘K
---
# Configure | Kameleo Developer Center
Configure
Copy
=====================
This page explains how to configure the Kameleo Engine using an appsettings.json file, environment variables, or command-line flags, and the precedence between them.
Prerequisites
-------------
* Kameleo installed (see [Installation](https://developer.kameleo.io/getting-started/installation/)
)
* Ability to run the Engine binary (headless or via Desktop)
* Text editor for creating `appsettings.json` (optional)
1\. Choose a configuration method
---------------------------------
You can supply values via (choose any combination):
1. File: `appsettings.json`
2. Environment variables
3. Command-line flags (`key=value`)
Use the method that matches your deployment style (local dev, CI, container, etc.).
##### Mix & match
You can keep stable defaults in the file and override the PAT via environment variables or flags. Precedence (highest wins): flags > environment variables > appsettings.json.
2\. Create `appsettings.json` (optional)
----------------------------------------
Location:
| Platform | Path |
| --- | --- |
| Windows | %APPDATA%\\Kameleo |
| macOS | ~/Library/Application Support/Kameleo |
| Docker (Linux) | `/data` |
| Docker (Windows) | `C:\data` |
Minimal example:
`{ "ListeningHost": "+", "ListeningPort": 5050, "Verbose": 1 }`
Complete key list and defaults are available at [Configuration options](https://developer.kameleo.io/reference/configuration-options/)
3\. Generate a personal access token (PAT)
------------------------------------------
A personal access token (PAT) authenticates the Engine with your Kameleo account. You must either provide a valid PAT every time the Engine starts (suited for automation scenarios) or login using the GUI once to access your account.
1. Open [https://login.kameleo.io/PAT](https://login.kameleo.io/PAT)
in your browser and sign in.
2. Click **Generate new token**.
3. Copy the token immediately — it is shown only once.
4. Store the token securely (e.g., in a secrets manager or environment variable). Do not commit it to source control.
##### Token visibility
The token value is displayed only at creation time. If you lose it, generate a new one and revoke the old token.
4\. (Alternative) Use environment variables
-------------------------------------------
Set variables before launching the Engine.
[Windows](https://developer.kameleo.io/getting-started/configure/#windows)
[macOS](https://developer.kameleo.io/getting-started/configure/#macos)
`$Env:PAT="your-pat"; ./Kameleo.Engine.exe`
5\. (Alternative) Use command-line flags
----------------------------------------
Append `key=value` arguments to the executable.
[Windows](https://developer.kameleo.io/getting-started/configure/#windows-1)
[macOS](https://developer.kameleo.io/getting-started/configure/#macos-1)
`./Kameleo.Engine.exe pat=your-pat`
6\. Start the Engine
--------------------
Run the Engine (Desktop auto-starts it). Example with flags shown above; omit if using file+env only.
7\. Verify
----------
Open: [http://localhost:5050/swagger](http://localhost:5050/swagger)
Expect the Swagger UI to load. Change `ListeningHost` / `ListeningPort` to relocate the endpoint (e.g., `0.0.0.0` for LAN access, custom port for collisions).
[On this page](https://developer.kameleo.io/getting-started/configure/)
* [Prerequisites](https://developer.kameleo.io/getting-started/configure/#prerequisites)
* [1\. Choose a configuration method](https://developer.kameleo.io/getting-started/configure/#1-choose-a-configuration-method)
* [2\. Create appsettings.json (optional)](https://developer.kameleo.io/getting-started/configure/#2-create-appsettingsjson-optional)
* [3\. Generate a personal access token (PAT)](https://developer.kameleo.io/getting-started/configure/#3-generate-a-personal-access-token-pat)
* [4\. (Alternative) Use environment variables](https://developer.kameleo.io/getting-started/configure/#4-alternative-use-environment-variables)
* [5\. (Alternative) Use command-line flags](https://developer.kameleo.io/getting-started/configure/#5-alternative-use-command-line-flags)
* [6\. Start the Engine](https://developer.kameleo.io/getting-started/configure/#6-start-the-engine)
* [7\. Verify](https://developer.kameleo.io/getting-started/configure/#7-verify)
⌘K
---
# Troubleshooting | Kameleo Developer Center
Troubleshooting
Copy
===========================
Use this guide to quickly locate user data and logs, interpret Engine exit codes, and gather the right diagnostics for troubleshooting Kameleo. Following these steps accelerates root-cause analysis and enables efficient support escalation.
Locate user data files
----------------------
Kameleo stores user-generated data (profiles, kernels, logs, settings) in a workspace directory.
[Windows](https://developer.kameleo.io/getting-started/troubleshooting/#windows)
[macOS](https://developer.kameleo.io/getting-started/troubleshooting/#macos)
[Linux-based container](https://developer.kameleo.io/getting-started/troubleshooting/#linux-based-container)
[Windows-based container](https://developer.kameleo.io/getting-started/troubleshooting/#windows-based-container)
Default location: `C:\Users\YOUR_USERNAME\AppData\Roaming\Kameleo`
Deleting this folder resets Kameleo (factory default) but permanently removes all profiles & settings.
Review log files
----------------
Daily log files live under the `Logs` subfolder. File pattern: `COMPONENT-YYYYMMDD.txt`. Increase verbosity by setting `Verbose` to `2` (see Configuration in Installation guide) only while debugging; revert to reduce noise.
[Windows](https://developer.kameleo.io/getting-started/troubleshooting/#windows-1)
[macOS](https://developer.kameleo.io/getting-started/troubleshooting/#macos-1)
[Linux-based container](https://developer.kameleo.io/getting-started/troubleshooting/#linux-based-container-1)
[Windows-based container](https://developer.kameleo.io/getting-started/troubleshooting/#windows-based-container-1)
Log files location: `C:\Users\YOUR_USERNAME\AppData\Roaming\Kameleo\Logs`
Engine exit codes
-----------------
Refer to the consolidated list in [Engine exit codes](https://developer.kameleo.io/reference/engine-exit-codes/)
for meanings and remediation guidance. Use these codes in scripts to branch on transient vs. persistent failures.
Gathering diagnostic info
-------------------------
1. Reproduce the issue with Verbose=2
2. Note timestamp & profileId (if relevant)
3. Collect the most recent log files
4. Export affected profile (if reproducible state matters)
Opening a ticket
----------------
Use the in-app **Report a Bug** button in the sidebar whenever you can. It automatically collects vital environment details and relevant log files so we can help you faster and with fewer back-and-forth questions.
1. Reproduce the issue (if possible).
2. In Kameleo, open the sidebar.
3. Click **Report a Bug**.
4. Describe what you expected vs. what happened.
5. Attach any helpful files (for example screenshots, scripts, or test data) that make it easier to reproduce the issue.
6. Submit the report.
If the app does not start, you cannot log in, or you cannot access the bug report feature, contact support through the [Help Center](https://help.kameleo.io/)
.
[On this page](https://developer.kameleo.io/getting-started/troubleshooting/)
* [Locate user data files](https://developer.kameleo.io/getting-started/troubleshooting/#locate-user-data-files)
* [Review log files](https://developer.kameleo.io/getting-started/troubleshooting/#review-log-files)
* [Engine exit codes](https://developer.kameleo.io/getting-started/troubleshooting/#engine-exit-codes)
* [Gathering diagnostic info](https://developer.kameleo.io/getting-started/troubleshooting/#gathering-diagnostic-info)
* [Opening a ticket](https://developer.kameleo.io/getting-started/troubleshooting/#opening-a-ticket)
⌘K
---
# Docker | Kameleo Developer Center
Docker
Copy
==================
This guide shows you how to run Kameleo inside a Docker container and expose the Local API on your host. Use the containerized deployment when you need an isolated, reproducible environment — for example, in CI pipelines, ephemeral workers, or remote hosts.
The [`kameleo/kameleo-app:latest`](https://hub.docker.com/r/kameleo/kameleo-app)
image is a multi-platform manifest covering both Windows (Server Core LTSC 2022) and Linux (Ubuntu 22.04). Docker automatically pulls the variant that matches your host OS, no separate tags are needed.
Prerequisites
-------------
[Linux-based container](https://developer.kameleo.io/integrations/docker/#linux-based-container)
[Windows-based container](https://developer.kameleo.io/integrations/docker/#windows-based-container)
* A Linux host (amd64), **or** Docker Desktop on Windows/macOS running in Linux containers mode (the default)
* Basic Docker experience (running containers, mounting volumes, using compose files)
* Valid Kameleo personal access token (PAT) — see [Configure](https://developer.kameleo.io/getting-started/configure/)
to generate one
##### Shared memory size
Always start the Linux container with `--shm-size=2g`. The default `/dev/shm` size of 64 MB is too small and will cause browser crashes.
Architecture
------------
Docker container
Junglefox instance
Profile #2 data
Chroma instance
Profile #1 data
Kameleo Cloud Services
Your automation scripts
Your browser
Local Engine instance
Web UI
Container layout & persistence
------------------------------
Kameleo runs under a non-administrative user inside the image. This improves isolation and reduces the surface for privilege escalation.
| Property | Linux | Windows |
| --- | --- | --- |
| **Runtime user** | `appuser` (UID 1001, non-root) | `ContainerUser` (built-in, non-admin) |
| **Data directory** | `/data` | `C:\data` |
Mount the data directory as a named Docker volume to persist state (profiles, kernels) across container recreations.
##### Use named volumes, not bind mounts
Always use a named volume (e.g. `-v kameleo-data:/data`) rather than a host bind mount (e.g. `-v ~/kameleo-data:/data`). The container runs as a non-root user (UID 1001 on Linux) and will be denied access to a host directory owned by a different user, causing an immediate startup failure.
If you don't mount the volume at all, every new container starts empty. Kameleo has to download all kernels again, which is slower and uses more bandwidth. Kernel downloads are rate limited, so starting many containers without a mounted volume can hit the limit and make startup fail.
Configuration methods
---------------------
You can configure Kameleo inside the container using the same precedence described in [Configure](https://developer.kameleo.io/getting-started/configure/)
. In container workflows you typically rely on environment variables or command-line flags appended to `docker run`.
Accepted environment variable names mirror the Engine keys with uppercase; see the full list and defaults in [Configuration options](https://developer.kameleo.io/reference/configuration-options/)
.
Mandatory credential must always be provided; without it the app will not authenticate and container startup will fail.
Steps
-----
### 1\. Run the container
Expose port 5050, pass the PAT, and mount the named volume for persistent data:
[Linux-based container](https://developer.kameleo.io/integrations/docker/#linux-based-container-1)
[Windows-based container](https://developer.kameleo.io/integrations/docker/#windows-based-container-1)
`docker run --platform linux/amd64 \ --shm-size=2g \ -p 5050:5050 \ -e PAT="your-pat" \ -v kameleo-data:/data \ kameleo/kameleo-app:latest`
### 2\. Verify the service
Open in a browser on the host and expect the Swagger UI to load:
`http://localhost:5050/swagger`
### 3\. Start your first profile
The container exposes the same Local API as the desktop app. Follow the [Quickstart guide](https://developer.kameleo.io/getting-started/quickstart/)
to install an SDK, create a client pointed at `http://localhost:5050`, and start your first automated profile.
Example with docker-compose
---------------------------
Use `docker-compose.yml` for repeatable infrastructure or CI pipelines:
[Linux-based container](https://developer.kameleo.io/integrations/docker/#linux-based-container-2)
[Windows-based container](https://developer.kameleo.io/integrations/docker/#windows-based-container-2)
`services: kameleo-app: image: "kameleo/kameleo-app:latest" platform: linux/amd64 ports: - "5050:5050" environment: PAT: your-pat volumes: - "kameleo-data:/data" shm_size: 2g restart: unless-stopped volumes: kameleo-data:`
Health checks
-------------
The published image already defines a `HEALTHCHECK` that periodically queries the `/general/healthcheck` endpoint and marks the container as `healthy` once Kameleo is responsive. Nothing extra is required; the health status is visible via the `State` column:
`docker ps`
If you build a custom derivative image (e.g., adding tools) and replace the base `CMD`, ensure you keep or re-add a healthcheck so orchestrators wait for readiness.
Web UI (only in Linux-based container)
--------------------------------------
The Linux container includes the Kameleo GUI, a browser-based interface served on port **80**. Expose that port to open it on your host:
`docker run --platform linux/amd64 \ --shm-size=2g \ -p 5050:5050 \ -p 80:80 \ -e PAT="your-pat" \ -v kameleo-data:/data \ kameleo/kameleo-app:latest`
Then open the GUI in your browser:
`http://localhost:80`
##### Limited functionality in Docker
The GUI served from a container has reduced functionality compared to the desktop application. Features that depend on direct filesystem access are not available or behave differently. Use the GUI for basic profile management and monitoring. For automation, use the [SDK](https://developer.kameleo.io/reference/api-reference/)
directly.
VNC viewer (only in Linux-based container)
------------------------------------------
The Kameleo GUI in the Linux container ships a built-in browser-based VNC viewer that lets you watch or interact with the virtual display where browsers run. It is accessible in any modern browser — no additional software is required.
The VNC server is disabled by default to keep resource utilization low. The VNC server starts automatically when opened from the GUI, or you can make it start by setting the VNCENABLE and VNCPASSWORD environment variables. This is necessary if you prefer a native VNC client (for example, RealVNC Viewer or TigerVNC), and you also need to expose port **5900** that carries the raw RFB protocol:
`docker run --platform linux/amd64 \ --shm-size=2g \ -p 5050:5050 \ -p 5900:5900 \ -e PAT="your-pat" \ -e VNCENABLE="1" \ -e VNCPASSWORD="your-vnc-password" \ -v kameleo-data:/data \ kameleo/kameleo-app:latest`
##### Expose VNC only on trusted networks
Port 5900 gives full control of the virtual display. Do not expose it on a public interface without a network-level access control layer such as a reverse proxy with authentication.
AWS ECS Support
---------------
Kameleo Docker containers are compatible with **AWS ECS (Elastic Container Service)**. The supported capacity provider depends on the platform:
| Platform | Capacity provider | Notes |
| --- | --- | --- |
| Windows | EC2 | Fargate does not support Windows containers with volumes |
| Linux | EC2 or Fargate | Fargate fully supports Linux containers |
When deploying to AWS ECS:
* For Windows, use EC2 capacity providers with Windows Server 2022-compatible instances.
* For Linux, EC2 and Fargate both work; Fargate is recommended for simpler infrastructure management.
* Configure appropriate instance types with sufficient resources for your Kameleo workload.
* Mount persistent storage using named volumes to preserve profile data across container restarts.
GPU support on Linux
--------------------
By default Kameleo uses software rendering inside the Linux container. If you mount the host GPU into the container, Kameleo automatically detects it and enables hardware-accelerated rendering in the browser. This can improve performance on GPU-intensive pages such as WebGL or canvas-heavy sites.
### Intel / AMD
Pass the DRI device directory and add the host device group IDs so the container user can access them:
`docker run --platform linux/amd64 \ --shm-size=2g \ --device /dev/dri \ --group-add $(stat -c '%g' /dev/dri/card0) \ --group-add $(stat -c '%g' /dev/dri/renderD128) \ -p 5050:5050 \ -e PAT="your-pat" \ -v kameleo-data:/data \ kameleo/kameleo-app:latest`
### NVIDIA
Install the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html)
on the host, then pass `--gpus all`:
`docker run --platform linux/amd64 \ --shm-size=2g \ --gpus all \ -p 5050:5050 \ -e PAT="your-pat" \ -v kameleo-data:/data \ kameleo/kameleo-app:latest`
##### No GPU? No problem
When no GPU device is mounted, the container falls back to software rendering automatically. No configuration change is needed.
Troubleshooting
---------------
### Container exits immediately
Check the container logs first:
`docker logs `
**Authentication error** (`PAT_INVALID`, exit code 111): the PAT is wrong or expired. Verify the `PAT` environment variable.
**Permission denied on `/data`** (`Access to the path '/data/...' is denied`): you are using a host bind mount instead of a named volume. Replace `-v ~/kameleo-data:/data` with `-v kameleo-data:/data`. The container runs as a non-root user and cannot write to a host directory owned by a different user.
### Service is not responding
Manually query the health endpoint to confirm whether the Engine started successfully:
`curl http://localhost:5050/general/healthcheck`
If the request times out, the container may still be starting up. Kernel downloads run on first launch and can take several minutes depending on your connection.
### Browser crashes on Linux
If browsers fail to open or crash immediately, the container is likely missing the `--shm-size=2g` flag. The default shared memory size of 64 MB is insufficient for browsers. Restart the container with `--shm-size=2g`.
### Kernel download fails or hits rate limit
Kernel downloads are rate limited. If you start many containers simultaneously without a mounted volume, each container downloads its own copy of all kernels and can exhaust the allowed download rate. Always mount the data directory so kernels are downloaded once and reused.
[On this page](https://developer.kameleo.io/integrations/docker/)
* [Prerequisites](https://developer.kameleo.io/integrations/docker/#prerequisites)
* [Architecture](https://developer.kameleo.io/integrations/docker/#architecture)
* [Container layout & persistence](https://developer.kameleo.io/integrations/docker/#container-layout--persistence)
* [Configuration methods](https://developer.kameleo.io/integrations/docker/#configuration-methods)
* [Steps](https://developer.kameleo.io/integrations/docker/#steps)
* [1\. Run the container](https://developer.kameleo.io/integrations/docker/#1-run-the-container)
* [2\. Verify the service](https://developer.kameleo.io/integrations/docker/#2-verify-the-service)
* [3\. Start your first profile](https://developer.kameleo.io/integrations/docker/#3-start-your-first-profile)
* [Example with docker-compose](https://developer.kameleo.io/integrations/docker/#example-with-docker-compose)
* [Health checks](https://developer.kameleo.io/integrations/docker/#health-checks)
* [Web UI (only in Linux-based container)](https://developer.kameleo.io/integrations/docker/#web-ui-only-in-linux-based-container)
* [VNC viewer (only in Linux-based container)](https://developer.kameleo.io/integrations/docker/#vnc-viewer-only-in-linux-based-container)
* [AWS ECS Support](https://developer.kameleo.io/integrations/docker/#aws-ecs-support)
* [GPU support on Linux](https://developer.kameleo.io/integrations/docker/#gpu-support-on-linux)
* [Intel / AMD](https://developer.kameleo.io/integrations/docker/#intel--amd)
* [NVIDIA](https://developer.kameleo.io/integrations/docker/#nvidia)
* [Troubleshooting](https://developer.kameleo.io/integrations/docker/#troubleshooting)
* [Container exits immediately](https://developer.kameleo.io/integrations/docker/#container-exits-immediately)
* [Service is not responding](https://developer.kameleo.io/integrations/docker/#service-is-not-responding)
* [Browser crashes on Linux](https://developer.kameleo.io/integrations/docker/#browser-crashes-on-linux)
* [Kernel download fails or hits rate limit](https://developer.kameleo.io/integrations/docker/#kernel-download-fails-or-hits-rate-limit)
⌘K
---
# Profiles | Kameleo Developer Center
Profiles
Copy
====================
Kameleo profiles are reusable containers that bundle a full browser fingerprint (hardware, network, environment traits) together with persistent state like cookies, history, storage, passwords, and bookmarks plus user customizations (proxy, extensions, switches). Each profile is tied to a specific kernel and can be started, stopped, exported/imported, and safely shared via locking when stored in the cloud. They let every session appear as a distinct consistent device that you can pause and later resume without losing context.
Components of a profile
-----------------------
| Category | Examples |
| --- | --- |
| Fingerprint attributes | UA, screen, WebGL, device memory, languages |
| Persistent state | Cookies, local/session storage, IndexedDB, cache |
| User customizations | Proxy config, extensions, language override, command switches |
| Kernel binding | Chroma or Junglefox version mapping |
| Metadata | Name, tags, storage location (local/cloud), creation time |
Lifecycle
---------
Virtual browser profiles can be in one of several lifetime states, each reflecting the status of the associated browser kernel and defining which actions can be performed:
* **Created**: The profile is created, but the browser kernel has not started.
* **Starting**: The browser kernel is in the process of starting.
* **Running**: The browser kernel is active and operational.
* **Terminating**: The browser kernel is shutting down.
* **Terminated**: The browser kernel is not running but was previously started.
* **Locked**: The profile is currently in use by another user on your team.
* **Loading**: The profile data or browser kernel is syncing with cloud storage.
On failure
On failure
Created
Starting
Running
Loading
Terminated
Terminating
Locked
Local vs cloud storage
----------------------
Kameleo supports both local and cloud-based profiles to meet different workflow needs.
**Local profiles** are stored directly on your device in Kameleo's workspace folder. They are faster to launch and manage, as all data is accessed and saved locally, so it is ideal for individual users or scenarios where performance is critical.
**Cloud profiles** are stored and synced via Kameleo's secure cloud infrastructure. Changes and updates to a cloud profile are instantly accessible to all team members, which makes collaboration seamless across multiple devices or users.
Cleanup strategy
----------------
* Periodically delete unused Terminated profiles to free disk space
* Export before risky experiments
* Tag profiles for audit & grouping (roadmap dependent)
[On this page](https://developer.kameleo.io/concepts/profiles/)
* [Components of a profile](https://developer.kameleo.io/concepts/profiles/#components-of-a-profile)
* [Lifecycle](https://developer.kameleo.io/concepts/profiles/#lifecycle)
* [Local vs cloud storage](https://developer.kameleo.io/concepts/profiles/#local-vs-cloud-storage)
* [Cleanup strategy](https://developer.kameleo.io/concepts/profiles/#cleanup-strategy)
⌘K
---
# Playwright | Kameleo Developer Center
Playwright
Copy
======================
Integrate Playwright with Kameleo to automate browsing using realistic, spoofed browser fingerprints.
You can start a profile in two ways:
1. **Explicit start**: Create the profile via the Local API and call `startProfile`. Use this when you need custom command-line switches, proxy settings, flags, or advanced options.
2. **Auto-start**: Skip `startProfile`. When Playwright connects (Chroma via CDP; Junglefox via `pw-bridge`) with the WebSocket endpoint, Kameleo automatically starts the profile using defaults.
After either approach, you control the browser with normal Playwright commands, then clean up (stop / export / delete) the profile.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* A Playwright-supported environment (Python, JavaScript, or C# with [Playwright library](https://playwright.dev/)
installed)
##### Playwright detection
Although fresh versions are recommended, version changes in Playwright can introduce detection signals. We recommend at least Playwright 1.53.0, or Playwright versions before 1.47.0 to avoid detection. See our [Code examples](https://developer.kameleo.io/reference/code-examples/)
for the latest versions we tested internally.
##### Playwright-Junglefox version alignment
Always verify and use the Playwright library version recommended for your current [Junglefox kernel release](https://kameleo.io/browser-kernel-releases)
. Mismatched versions can cause launch, connection, or protocol errors.
##### Downloading pw-bridge
The `pw-bridge` executable is bundled inside the SDK packages, so `JunglefoxHelper` finds it for you. You only need the standalone download if you are not using an SDK, for whatever reason.
It currently also ships with the Kameleo app, but that is deprecated and will be removed in 6.0. The SDK packages keep bundling it. Download it for your platform:
* [Windows x64](https://get.kameleo.io/pw-bridge/2.0.0/win-x64/pw-bridge.exe)
* [Linux x64](https://get.kameleo.io/pw-bridge/2.0.0/linux-x64/pw-bridge)
* [macOS arm64](https://get.kameleo.io/pw-bridge/2.0.0/osx-arm64/pw-bridge)
On Linux and macOS, make it executable with `chmod +x pw-bridge`. Then launch Playwright with it as the browser executable, passing `-target ws://localhost:5050/playwright/{profileId}` as its argument.
Best practices
--------------
* Do not add third-party stealth / fingerprint patches (playwright-extra, Canvas defenders, etc.). They can reduce masking quality.
* Use one browser context per profile. Create multiple Kameleo profiles instead of multiple contexts.
Option 1: Explicitly start the profile (customizable)
-----------------------------------------------------
Use this when you must set advanced startup parameters. Example below show a start with some custom settings.
### 1\. Create a profile
[Python](https://developer.kameleo.io/integrations/playwright/#python)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript)
[C#](https://developer.kameleo.io/integrations/playwright/#c)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fingerprints = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome' ) create_req = CreateProfileRequest( fingerprint_id=fingerprints[0].id, name='playwright explicit start example' ) profile = client.profile.create_profile(create_req)`
### 2\. Start the profile (customization point)
Below are three common customization patterns. Pick one (or combine arguments + preferences) before connecting Playwright. The browser must be stopped and restarted to apply a different set.
1. Add command-line arguments (e.g. mute audio)
2. Pass extra options / capabilities (e.g. disable background throttling)
3. Set native browser preferences (e.g. disable images)
[Python](https://developer.kameleo.io/integrations/playwright/#python-1)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-1)
[C#](https://developer.kameleo.io/integrations/playwright/#c-1)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( arguments=["--mute-audio"], additional_options=[ Preference(key='pageLoadStrategy', value='eager'), ], preferences=[ Preference(key='profile.managed_default_content_settings.images', value=2), ] ))`
### 3\. Connect Playwright
Implementation differs by kernel.
#### Chroma kernel (Chromium, auto-start)
Connect over CDP WebSocket: `ws://localhost:{port}/playwright/{profileId}`
[Python](https://developer.kameleo.io/integrations/playwright/#python-2)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-2)
[C#](https://developer.kameleo.io/integrations/playwright/#c-2)
`from playwright.sync_api import sync_playwright browser_ws_endpoint = f'ws://localhost:5050/playwright/{profile.id}' with sync_playwright() as playwright: browser = playwright.chromium.connect_over_cdp(endpoint_url=browser_ws_endpoint, timeout=90_000)`
#### Junglefox kernel (Firefox, auto-start)
Playwright cannot attach to an already running Firefox instance, so use the Kameleo SDK's `pw-bridge` helper that translates commands.
[Python](https://developer.kameleo.io/integrations/playwright/#python-3)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-3)
[C#](https://developer.kameleo.io/integrations/playwright/#c-3)
`from playwright.sync_api import sync_playwright from kameleo.local_api_client import JunglefoxHelper with sync_playwright() as playwright: context = playwright.firefox.launch_persistent_context( '', executable_path=JunglefoxHelper.get_bridge_path(), args=JunglefoxHelper.get_bridge_args(client, profile), no_viewport=True, timeout=90_000, )`
### 4\. Run Playwright commands
Use standard Playwright APIs.
#### Chroma kernel
[Python](https://developer.kameleo.io/integrations/playwright/#python-4)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-4)
[C#](https://developer.kameleo.io/integrations/playwright/#c-4)
`context = browser.contexts[0] page = context.new_page() page.goto('https://google.com')`
#### Junglefox kernel
[Python](https://developer.kameleo.io/integrations/playwright/#python-5)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-5)
[C#](https://developer.kameleo.io/integrations/playwright/#c-5)
`page = context.new_page() page.goto('https://google.com')`
##### Warning
Do not modify browser or network settings via Playwright; configure them with Kameleo before starting the profile.
Option 2: Auto-start the profile (simpler)
------------------------------------------
Skip the explicit start call. Kameleo starts the profile automatically on the first Playwright connection. Use this for quick scripts where default startup behavior is enough.
### 1\. Create the profile (same as before, no start call later)
[Python](https://developer.kameleo.io/integrations/playwright/#python-6)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-6)
[C#](https://developer.kameleo.io/integrations/playwright/#c-6)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest from playwright.sync_api import sync_playwright client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fps = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome', ) profile = client.profile.create_profile(CreateProfileRequest( fingerprint_id=fps[0].id, name='playwright auto-start example' ))`
### 2\. Connect (auto-start happens here)
Implementation differs by kernel. When you connect, the profile starts automatically.
#### Chroma kernel (Chromium)
[Python](https://developer.kameleo.io/integrations/playwright/#python-7)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-7)
[C#](https://developer.kameleo.io/integrations/playwright/#c-7)
`browser_ws_endpoint = f'ws://localhost:5050/playwright/{profile.id}' with sync_playwright() as playwright: browser = playwright.chromium.connect_over_cdp(endpoint_url=browser_ws_endpoint, timeout=90_000) context = browser.contexts[0] page = context.new_page() page.goto('https://wikipedia.org')`
#### Junglefox kernel (Firefox)
Playwright cannot attach to an already running Firefox instance, so use the Kameleo SDK's `pw-bridge` helper that translates commands.
Auto-start triggers on first command relay.
[Python](https://developer.kameleo.io/integrations/playwright/#python-8)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-8)
[C#](https://developer.kameleo.io/integrations/playwright/#c-8)
`from playwright.sync_api import sync_playwright from kameleo.local_api_client import JunglefoxHelper with sync_playwright() as playwright: context = playwright.firefox.launch_persistent_context( '', executable_path=JunglefoxHelper.get_bridge_path(), args=JunglefoxHelper.get_bridge_args(client, profile), no_viewport=True, timeout=90_000, ) page = context.new_page() page.goto('https://wikipedia.org')`
Cleanup (stop, export, delete)
------------------------------
Always stop the profile to persist its state. Optionally export it for backup or delete it to reclaim space.
### Stop, export, or delete
[Python](https://developer.kameleo.io/integrations/playwright/#python-9)
[JavaScript](https://developer.kameleo.io/integrations/playwright/#javascript-9)
[C#](https://developer.kameleo.io/integrations/playwright/#c-9)
`import os from kameleo.local_api_client.models import ExportProfileRequest client.profile.stop_profile(profile.id) export_path = f'{os.path.dirname(os.path.realpath(__file__))}/test.kameleo' client.profile.export_profile(profile.id, body=ExportProfileRequest(path=export_path)) client.profile.delete_profile(profile.id)`
Full examples on GitHub
-----------------------
| Language | Chroma kernel | Junglefox kernel |
| --- | --- | --- |
| Python | [Chroma Python Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_playwright_to_chrome/app.py) | [Junglefox Python Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_playwright_to_firefox/app.py) |
| JavaScript | [Chroma JS Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_playwright_to_chrome/index.js) | [Junglefox JS Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_playwright_to_firefox/index.js) |
| C# | [Chroma C# Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_playwright_to_chrome/Program.cs) | [Junglefox C# Example](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_playwright_to_firefox/Program.cs) |
[On this page](https://developer.kameleo.io/integrations/playwright/)
* [Prerequisites](https://developer.kameleo.io/integrations/playwright/#prerequisites)
* [Best practices](https://developer.kameleo.io/integrations/playwright/#best-practices)
* [Option 1: Explicitly start the profile (customizable)](https://developer.kameleo.io/integrations/playwright/#option-1-explicitly-start-the-profile-customizable)
* [1\. Create a profile](https://developer.kameleo.io/integrations/playwright/#1-create-a-profile)
* [2\. Start the profile (customization point)](https://developer.kameleo.io/integrations/playwright/#2-start-the-profile-customization-point)
* [3\. Connect Playwright](https://developer.kameleo.io/integrations/playwright/#3-connect-playwright)
* [Chroma kernel (Chromium, auto-start)](https://developer.kameleo.io/integrations/playwright/#chroma-kernel-chromium-auto-start)
* [Junglefox kernel (Firefox, auto-start)](https://developer.kameleo.io/integrations/playwright/#junglefox-kernel-firefox-auto-start)
* [4\. Run Playwright commands](https://developer.kameleo.io/integrations/playwright/#4-run-playwright-commands)
* [Chroma kernel](https://developer.kameleo.io/integrations/playwright/#chroma-kernel)
* [Junglefox kernel](https://developer.kameleo.io/integrations/playwright/#junglefox-kernel)
* [Option 2: Auto-start the profile (simpler)](https://developer.kameleo.io/integrations/playwright/#option-2-auto-start-the-profile-simpler)
* [1\. Create the profile (same as before, no start call later)](https://developer.kameleo.io/integrations/playwright/#1-create-the-profile-same-as-before-no-start-call-later)
* [2\. Connect (auto-start happens here)](https://developer.kameleo.io/integrations/playwright/#2-connect-auto-start-happens-here)
* [Chroma kernel (Chromium)](https://developer.kameleo.io/integrations/playwright/#chroma-kernel-chromium)
* [Junglefox kernel (Firefox)](https://developer.kameleo.io/integrations/playwright/#junglefox-kernel-firefox)
* [Cleanup (stop, export, delete)](https://developer.kameleo.io/integrations/playwright/#cleanup-stop-export-delete)
* [Stop, export, or delete](https://developer.kameleo.io/integrations/playwright/#stop-export-or-delete)
* [Full examples on GitHub](https://developer.kameleo.io/integrations/playwright/#full-examples-on-github)
⌘K
---
# Kernels | Kameleo Developer Center
Kernels
Copy
===================
A browser kernel (Chroma or Junglefox) is the component that executes JavaScript, draws pages, and exposes the low‑level browser APIs that sophisticated bot‑detection scripts interrogate. Kernel version, therefore, is part of your fingerprint. Kameleo’s multi-kernel architecture lets every browsing profile run on the most suitable kernel at any moment. By separating the Kameleo Engine from its kernels and shipping each kernel independently, we can minimize fingerprint mismatches, react to upstream security patches within days, and keep profile start‑up snappy because the kernel you need is already cached locally.
##### Latest kernel releases
For the always up-to-date list of shipped Chroma and Junglefox kernel versions, see the [Browser Kernel Releases](https://kameleo.io/browser-kernel-releases)
page.
Kernel mapping
--------------
| Fingerprint | Kernel | Note |
| --- | --- | --- |
| Chrome | Chroma | Natively supported |
| Edge | Chroma | Natively supported |
| Firefox | Junglefox | Natively supported |
| Safari | Chroma | WebKit-based kernels are not currently supported |
| iOS Safari | Chroma | Emulated through Chroma's mobile device mode |
| Android Chrome | Chroma | Emulated through Chroma's mobile device mode |
Selection logic
---------------
1. Read the profile’s target browser name and version (e.g., Chrome 145.0.x).
2. Enumerate local cache plus available remote kernel builds for that browser family.
3. Pick the best match: exact version if present; otherwise closest newer patch; otherwise closest older patch.
4. If the chosen kernel isn’t cached yet, download it once and store it for reuse.
5. Launch the kernel with the profile’s configuration (fingerprint details, proxy, command-line switches, etc.).
You can trigger this selection and download step explicitly ahead of time, so the browser launches immediately when you start the profile instead of waiting for an implicit kernel download.
Example:
[Python](https://developer.kameleo.io/concepts/kernels/#python)
[JavaScript](https://developer.kameleo.io/concepts/kernels/#javascript)
[C#](https://developer.kameleo.io/concepts/kernels/#c)
`kernel = client.profile.install_profile_kernel(profile.id)`
Update cadence
--------------
Kernels ship separately from the GUI and the Engine so you get:
* Faster security fixes
* Fewer full app updates
* Safe rollback (previous kernel kept until new one is validated)
We release new Chroma kernels within 5 days of each Stable Chrome release. Junglefox updates ship about every two months. Get release notifications on our [Telegram channel](https://t.me/kameleoapp)
or the [Browser Kernel Releases](https://kameleo.io/browser-kernel-releases)
page.
Integrity & consistency
-----------------------
Common mismatch types this multi-kernel approach prevents:
* **JavaScript version drift:** UA says a newer Chrome/Firefox, but new JS / Intl APIs are missing.
* **CSS support gaps:** fingerprint claims :has() or container queries that the browser kernel does not yet implement.
* **Graphics anomalies:** reported version implies newer ANGLE / GPU caps than the shaders & renderer hashes expose.
* **Network / TLS stack skew:** cipher suite ordering or ALPN set belongs to an older release than the claimed version.
By selecting the exact or closest kernel, cross‑layer tests produce a coherent, low‑risk fingerprint.
Parallelism
-----------
Multiple profiles can launch distinct kernel versions concurrently. Disk cache isolates binary sets; memory overhead scales mostly with active renderer processes.
[On this page](https://developer.kameleo.io/concepts/kernels/)
* [Kernel mapping](https://developer.kameleo.io/concepts/kernels/#kernel-mapping)
* [Selection logic](https://developer.kameleo.io/concepts/kernels/#selection-logic)
* [Update cadence](https://developer.kameleo.io/concepts/kernels/#update-cadence)
* [Integrity & consistency](https://developer.kameleo.io/concepts/kernels/#integrity--consistency)
* [Parallelism](https://developer.kameleo.io/concepts/kernels/#parallelism)
⌘K
---
# Filter browser fingerprints | Kameleo Developer Center
Filter browser fingerprints
Copy
=======================================
In this tutorial you will query the `SearchFingerprints` endpoint to retrieve candidate browser fingerprints, refine the results with filters (device type, OS family, browser product, version constraints), and pick one to use when creating a profile.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app is running locally (default API base URL: `http://localhost:5050`).
* Network access to the local API port (no firewall blocking 5050).
Parameter reference
-------------------
The `SearchFingerprints` endpoint accepts these optional parameters (all are filters; omit to broaden results):
| Name | Description | Examples |
| --- | --- | --- |
| `deviceType` | Device category. Accepts `desktop`, `mobile`. **Defaults to desktop** | `desktop`, `mobile` |
| `osFamily` | Operating system family. Accepts `windows`, `macos`, `linux`, `android`, `ios`. **Defaults to the Engine's OS**. | `windows`, `macos` |
| `browserProduct` | Browser engine/product. Accepts `chrome`, `firefox`, `edge`, `safari`. **Defaults to Chrome** | `chrome`, `edge` |
| `browserVersion` | Version filter. Optional comparator + major number (`>145`, `<=147`, `=146`). No comparator means equality. | `>145`, `146`, `<=147` |
Notes:
* Unspecified fields give you the recommended defaults - desktop Chrome fingerprints, matching your Engine's host OS.
* Defaults only apply when compatible with your filters - e.g. your host OS won't be forced if you specify mobile.
* The API returns an array of `FingerprintPreview` objects (see [API reference](https://developer.kameleo.io/reference/api-reference/)
). Each preview contains enough metadata for choosing a candidate; you supply its attributes when creating a profile.
Basic search example
--------------------
The endpoint always returns up to 25 matching items ordered by newest browser versions first. Repeating the same query yields a different random subset - cache or persist the one you pick if you need stability. Below you'll see how to fetch Windows Chrome fingerprints newer than version 145.
##### API rate limits
Each fingerprint search request counts toward your API quota. Avoid rapid polling loops; broaden filters or cache previously retrieved candidates instead of re-querying repeatedly. See the [Usage limits](https://developer.kameleo.io/reference/usage-limits/)
page for details.
[Python](https://developer.kameleo.io/tutorials/filtering-fingerprints/#python)
[JavaScript](https://developer.kameleo.io/tutorials/filtering-fingerprints/#javascript)
[C#](https://developer.kameleo.io/tutorials/filtering-fingerprints/#c)
`fingerprints = client.fingerprint.search_fingerprints( device_type='desktop', os_family='windows', browser_product='chrome', browser_version='>145', ) if not fingerprints: print('No fingerprints found; broaden filters (remove version or add more osFamily values).') else: fp = fingerprints[0] print(f'Picked fingerprint: {fp.browser.product} {fp.browser.version} on {fp.os.family}')`
Picking quality candidates
--------------------------
Follow these guidelines:
* Use the default options for the best results. The below advice is applied automatically for fingerprint selection, but you can explore other options too.
* Align `osFamily`, proxy geo, and locale (e.g. `windows` + US proxy + `en-US`) for coherent targeting.
* Prefer current stable major versions (`chrome`, `edge`) unless you have a site-specific requirement.
* Avoid extremely old or rare combinations unless testing edge behavior.
* If you need mobile emulation, set `deviceType=mobile` and constrain `osFamily` to `android` or `ios` + a matching browser (Chrome for Android; Safari for iOS).
##### Version filtering
Start broad: query without `browserVersion`, inspect results, then narrow (e.g. add `>145`). Empty list? Remove comparator or lower the version.
Handling empty results
----------------------
If a query returns zero fingerprints:
1. Remove the `browserVersion` filter.
2. Confirm spelling (`macos`, not `macOS`; `osFamily` not `platform`).
3. Try only `deviceType` first, then incrementally add filters.
Programmatically, detect empties and fallback to a broader search (e.g. call again without version) or more common OS + browser combinations.
[On this page](https://developer.kameleo.io/tutorials/filtering-fingerprints/)
* [Prerequisites](https://developer.kameleo.io/tutorials/filtering-fingerprints/#prerequisites)
* [Parameter reference](https://developer.kameleo.io/tutorials/filtering-fingerprints/#parameter-reference)
* [Basic search example](https://developer.kameleo.io/tutorials/filtering-fingerprints/#basic-search-example)
* [Picking quality candidates](https://developer.kameleo.io/tutorials/filtering-fingerprints/#picking-quality-candidates)
* [Handling empty results](https://developer.kameleo.io/tutorials/filtering-fingerprints/#handling-empty-results)
⌘K
---
# Teamwork | Kameleo Developer Center
Teamwork
Copy
====================
Team collaboration in Kameleo rests on three pillars that pair with reusable profiles:
1. Cloud Storage – shared, synced access to profile data
2. Profile Groups – organized containers + granular sharing
3. Team Management – controlling who is on the team and their privileges
Together they let multiple operators work on many identities without clashes, data loss, or chaotic hand‑offs.
Cloud storage
-------------
Cloud‑stored profiles live in the Kameleo backend instead of only your disk. Benefits:
| Capability | Local profile | Cloud profile |
| --- | --- | --- |
| Visibility | Private (per machine) | Shareable (via groups) |
| Cross‑device use | Export / import manually | Automatic sync (create on laptop, open on VM) |
| Collaboration safety | Manual coordination | Built‑in locking (no dual runs) |
| Backup / durability | Your responsibility | Managed redundancy |
| Privacy isolation | Strong (never leaves PC) | Controlled via group membership |
Key concepts:
* Syncing – profile data is uploading or downloading the latest state.
* Locked – another user/device is currently running it; start is blocked to protect cookie/history integrity.
* Single runner rule – only one active instance of a profile at a time (prevents divergent fingerprints & ban risk).
* Capacity – unlimited local profiles on all plans; cloud profile quota depends on plan tier. Enterprise can request higher limits via support.
Choose cloud when: multiple people touch the same identities, you switch workstations, or you need centralized oversight. Stay local for rapid throw‑away experiments, maximum privacy, or high‑performance workloads where eliminating sync overhead matters (e.g., intensive scraping bursts, CPU/GPU heavy automation labs).
Profile Groups
--------------
Groups bundle related cloud profiles (client A, campaign Q4, anti‑fraud research, etc.) and apply a single sharing policy to all contained profiles. Ungrouped cloud profiles are private to their creator (except Team Owner visibility mode), while local profiles remain machine‑local.
Group advantages:
* Organization – filter by group instead of scrolling hundreds of entries.
* Bulk actions – move / tag / archive sets faster.
* Access boundary – invite only the colleagues who need those identities.
* Separation of concerns – keep unrelated client data isolated.
Team management
---------------
Team membership decides who is on your account. Groups then control which profiles each person can use. You can add many team members but give each only the groups they need.
Core actors:
| Scope | Role / Mode | Summary |
| --- | --- | --- |
| Team (account) | Team Owner | Billing & seat control, can view/edit all cloud content (owner mode). |
| Group | Admin | Full rights on the group + can share / change roles / delete profiles. |
| Group | Analyst | Create, run, modify, delete profiles; cannot change sharing. |
| Group | Member | Run (start/stop) only; read fingerprint metadata; no edits or sharing. |
Inviting / removing teammates does not automatically expose every group - only those shared or owned. Ungrouped cloud profiles stay private except to the Team Owner for quota oversight. Need stricter isolation? Keep profiles local.
How they work together (example flow)
-------------------------------------
1. Team lead creates 10 baseline cloud profiles; sync completes.
2. Moves them into a new group “Onboarding”.
3. Shares the group: adds two analysts and one member.
4. Analyst starts Profile A, it becomes locked. Member sees lock, waits.
5. Analyst stops Profile A, lock clears. Member starts it to continue session seamlessly.
6. Team Owner audits group usage and storage without altering running sessions.
Quick FAQ
---------
| Question | Short answer |
| --- | --- |
| Can two devices run one cloud profile? | No, Lock enforces single active runner. |
| Are local profiles still unlimited? | Yes, all plans. |
| Do I need a group to share a profile? | Yes, sharing is applied at group level. Move the profile into a group first. |
| Can a Member export a profile? | No, only Analyst or Admin. |
| How to keep a profile totally private? | Keep it local or leave it ungrouped in cloud (Team Owner may still audit usage). |
| What if sync seems stuck? | Wait, then retry; persistent issues → check network or contact support. |
[On this page](https://developer.kameleo.io/concepts/teamwork/)
* [Cloud storage](https://developer.kameleo.io/concepts/teamwork/#cloud-storage)
* [Profile Groups](https://developer.kameleo.io/concepts/teamwork/#profile-groups)
* [Team management](https://developer.kameleo.io/concepts/teamwork/#team-management)
* [How they work together (example flow)](https://developer.kameleo.io/concepts/teamwork/#how-they-work-together-example-flow)
* [Quick FAQ](https://developer.kameleo.io/concepts/teamwork/#quick-faq)
⌘K
---
# Selenium | Kameleo Developer Center
Selenium
Copy
====================
Integrate Selenium WebDriver with Kameleo to automate browsing using realistic, spoofed browser fingerprints.
You can start a profile in two ways:
1. **Explicit start**: Create the profile via the Local API and call `startProfile`. Use this when you need custom command-line switches, proxy settings, flags, or advanced options.
2. **Auto-start**: Skip `startProfile`. When Selenium connects with the `kameleo:profileId` capability, Kameleo automatically starts the profile using defaults.
After either approach, you control the browser with normal Selenium commands, then clean up (stop / export / delete) the profile.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* A Selenium-capable environment (Python, JavaScript, or C# with [Selenium libraries](https://www.selenium.dev/)
installed)
Option 1: Explicitly start the profile (customizable)
-----------------------------------------------------
Use this when you must set advanced startup parameters. Example below show a start with some custom settings.
### 1\. Create a profile
[Python](https://developer.kameleo.io/integrations/selenium/#python)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript)
[C#](https://developer.kameleo.io/integrations/selenium/#c)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fingerprints = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome' ) create_req = CreateProfileRequest( fingerprint_id=fingerprints[0].id, name='selenium explicit start example' ) profile = client.profile.create_profile(create_req)`
### 2\. Start the profile (customization point)
Below are three common customization patterns. Pick one (or combine arguments + preferences) before connecting Selenium. The browser must be stopped and restarted to apply a different set.
1. Add command-line arguments (e.g. mute audio)
2. Pass extra Selenium options / capabilities (e.g. eager page load strategy)
3. Set native browser preferences (e.g. disable images)
[Python](https://developer.kameleo.io/integrations/selenium/#python-1)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-1)
[C#](https://developer.kameleo.io/integrations/selenium/#c-1)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( arguments=["--mute-audio"], additional_options=[ Preference(key='pageLoadStrategy', value='eager'), ], preferences=[ Preference(key='profile.managed_default_content_settings.images', value=2), ] ))`
### 3\. Connect Selenium WebDriver
Point Selenium to `http://localhost:{port}/webdriver` and supply `kameleo:profileId`.
[Python](https://developer.kameleo.io/integrations/selenium/#python-2)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-2)
[C#](https://developer.kameleo.io/integrations/selenium/#c-2)
`from selenium import webdriver options = webdriver.ChromeOptions() options.set_capability('kameleo:profileId', profile.id) driver = webdriver.Remote( command_executor='http://localhost:5050/webdriver', options=options )`
### 4\. Run Selenium commands
[Python](https://developer.kameleo.io/integrations/selenium/#python-3)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-3)
[C#](https://developer.kameleo.io/integrations/selenium/#c-3)
`driver.get('https://google.com')`
Option 2: Auto-start the profile (simpler)
------------------------------------------
Skip the explicit start call. Kameleo starts the profile automatically on the first WebDriver connection. Use this for quick scripts where default startup behavior is enough.
### 1\. Create the profile (same as before, no start call later)
[Python](https://developer.kameleo.io/integrations/selenium/#python-4)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-4)
[C#](https://developer.kameleo.io/integrations/selenium/#c-4)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest from selenium import webdriver client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fps = client.fingerprint.search_fingerprints(device_type='desktop', browser_product='chrome') profile = client.profile.create_profile(CreateProfileRequest( fingerprint_id=fps[0].id, name='selenium auto-start example' ))`
### 2\. Connect (auto-start happens here)
[Python](https://developer.kameleo.io/integrations/selenium/#python-5)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-5)
[C#](https://developer.kameleo.io/integrations/selenium/#c-5)
`options = webdriver.ChromeOptions() options.set_capability('kameleo:profileId', profile.id) driver = webdriver.Remote( command_executor='http://localhost:5050/webdriver', options=options ) driver.get('https://wikipedia.org')`
Cleanup (stop, export, delete)
------------------------------
Always stop the profile to persist its state. Optionally export it for backup or delete it to reclaim space.
### Stop, export, or delete
[Python](https://developer.kameleo.io/integrations/selenium/#python-6)
[JavaScript](https://developer.kameleo.io/integrations/selenium/#javascript-6)
[C#](https://developer.kameleo.io/integrations/selenium/#c-6)
`import os from kameleo.local_api_client.models import ExportProfileRequest client.profile.stop_profile(profile.id) export_path = f'{os.path.dirname(os.path.realpath(__file__))}/test.kameleo' client.profile.export_profile(profile.id, body=ExportProfileRequest(path=export_path)) client.profile.delete_profile(profile.id)`
Full examples on GitHub
-----------------------
| Language | Example repository link |
| --- | --- |
| Python | [Python code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_selenium/app.py) |
| JavaScript | [JavaScript code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_selenium/index.js) |
| C# | [C# code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_selenium/Program.cs) |
[On this page](https://developer.kameleo.io/integrations/selenium/)
* [Prerequisites](https://developer.kameleo.io/integrations/selenium/#prerequisites)
* [Option 1: Explicitly start the profile (customizable)](https://developer.kameleo.io/integrations/selenium/#option-1-explicitly-start-the-profile-customizable)
* [1\. Create a profile](https://developer.kameleo.io/integrations/selenium/#1-create-a-profile)
* [2\. Start the profile (customization point)](https://developer.kameleo.io/integrations/selenium/#2-start-the-profile-customization-point)
* [3\. Connect Selenium WebDriver](https://developer.kameleo.io/integrations/selenium/#3-connect-selenium-webdriver)
* [4\. Run Selenium commands](https://developer.kameleo.io/integrations/selenium/#4-run-selenium-commands)
* [Option 2: Auto-start the profile (simpler)](https://developer.kameleo.io/integrations/selenium/#option-2-auto-start-the-profile-simpler)
* [1\. Create the profile (same as before, no start call later)](https://developer.kameleo.io/integrations/selenium/#1-create-the-profile-same-as-before-no-start-call-later)
* [2\. Connect (auto-start happens here)](https://developer.kameleo.io/integrations/selenium/#2-connect-auto-start-happens-here)
* [Cleanup (stop, export, delete)](https://developer.kameleo.io/integrations/selenium/#cleanup-stop-export-delete)
* [Stop, export, or delete](https://developer.kameleo.io/integrations/selenium/#stop-export-or-delete)
* [Full examples on GitHub](https://developer.kameleo.io/integrations/selenium/#full-examples-on-github)
⌘K
---
# Puppeteer | Kameleo Developer Center
Puppeteer
Copy
=====================
Integrate Puppeteer with Kameleo to automate browsing using realistic, spoofed browser fingerprints (Chroma kernel only).
You can start a profile in two ways:
1. **Explicit start**: Create the profile via the Local API and call `startProfile`. Use this when you need custom command-line switches, proxy settings, flags, or advanced options.
2. **Auto-start**: Skip `startProfile`. When Puppeteer connects with the WebSocket endpoint, Kameleo automatically starts the profile using defaults.
After either approach, you control the browser with normal Puppeteer commands, then clean up (stop / export / delete) the profile.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* A Puppeteer-compatible environment (Python, JavaScript, or C# with [Puppeteer library](https://pptr.dev/)
installed)
Limitations & best practices
----------------------------
* Puppeteer works only with Chroma (Chromium-based) kernels.
* Do not add third-party stealth / fingerprint patches (puppeteer-extra-plugin-stealth, Canvas defenders, etc.). They can reduce masking quality.
* Use one browser context per profile. Create multiple Kameleo profiles instead of multiple contexts.
Option 1: Explicitly start the profile (customizable)
-----------------------------------------------------
Use this when you must set advanced startup parameters. Example below show a start with some custom settings.
### 1\. Create a profile
[Python](https://developer.kameleo.io/integrations/puppeteer/#python)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fingerprints = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome' ) create_req = CreateProfileRequest( fingerprint_id=fingerprints[0].id, name='puppeteer explicit start example' ) profile = client.profile.create_profile(create_req)`
### 2\. Start the profile (customization point)
Below are three common customization patterns. Pick one (or combine arguments + preferences) before connecting Puppeteer. The browser must be stopped and restarted to apply a different set.
1. Add command-line arguments (e.g. mute audio)
2. Pass extra options / capabilities (e.g. disable background throttling)
3. Set native browser preferences (e.g. disable images)
[Python](https://developer.kameleo.io/integrations/puppeteer/#python-1)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript-1)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c-1)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( arguments=["--mute-audio"], additional_options=[ Preference(key='pageLoadStrategy', value='eager'), ], preferences=[ Preference(key='profile.managed_default_content_settings.images', value=2), ] ))`
### 3\. Connect Puppeteer (Chroma only)
Use the WebSocket URL `ws://localhost:{port}/puppeteer/{profileId}` to connect.
[Python](https://developer.kameleo.io/integrations/puppeteer/#python-2)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript-2)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c-2)
`from pyppeteer import connect browser_ws_endpoint = f'ws://localhost:5050/puppeteer/{profile.id}' browser = await connect(browserWSEndpoint=browser_ws_endpoint, defaultViewport=None)`
### 4\. Run Puppeteer commands
[Python](https://developer.kameleo.io/integrations/puppeteer/#python-3)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript-3)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c-3)
`page = await browser.newPage() await page.goto('https://google.com')`
Option 2: Auto-start the profile (simpler)
------------------------------------------
Skip the explicit start call. Kameleo starts the profile automatically on the first Puppeteer connection. Use this for quick scripts where default startup behavior is enough.
### 1\. Create the profile (same as before, no start call later)
[Python](https://developer.kameleo.io/integrations/puppeteer/#python-4)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript-4)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c-4)
`from kameleo.local_api_client import KameleoLocalApiClient from kameleo.local_api_client.models import CreateProfileRequest from pyppeteer import connect import asyncio async def main(): client = KameleoLocalApiClient(endpoint='http://localhost:5050') client.verify_engine_ready() fps = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome', ) profile = client.profile.create_profile(CreateProfileRequest( fingerprint_id=fps[0].id, name='puppeteer auto-start example' )) browser_ws_endpoint = f'ws://localhost:5050/puppeteer/{profile.id}' browser = await connect(browserWSEndpoint=browser_ws_endpoint, defaultViewport=None) page = await browser.newPage() await page.goto('https://wikipedia.org') asyncio.run(main())`
Cleanup (stop, export, delete)
------------------------------
Always stop the profile to persist its state. Optionally export it for backup or delete it to reclaim space.
### Stop, export, or delete
[Python](https://developer.kameleo.io/integrations/puppeteer/#python-5)
[JavaScript](https://developer.kameleo.io/integrations/puppeteer/#javascript-5)
[C#](https://developer.kameleo.io/integrations/puppeteer/#c-5)
`import os from kameleo.local_api_client.models import ExportProfileRequest client.profile.stop_profile(profile.id) export_path = f'{os.path.dirname(os.path.realpath(__file__))}/test.kameleo' client.profile.export_profile(profile.id, body=ExportProfileRequest(path=export_path)) client.profile.delete_profile(profile.id)`
Full examples on GitHub
-----------------------
| Language | Chroma kernel | Junglefox kernel |
| --- | --- | --- |
| Python | [Python code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_puppeteer/app.py) | Not supported |
| JavaScript | [JavaScript code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_puppeteer/index.js) | Not supported |
| C# | [C# code on GitHub](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_puppeteer/Program.cs) | Not supported |
[On this page](https://developer.kameleo.io/integrations/puppeteer/)
* [Prerequisites](https://developer.kameleo.io/integrations/puppeteer/#prerequisites)
* [Limitations & best practices](https://developer.kameleo.io/integrations/puppeteer/#limitations--best-practices)
* [Option 1: Explicitly start the profile (customizable)](https://developer.kameleo.io/integrations/puppeteer/#option-1-explicitly-start-the-profile-customizable)
* [1\. Create a profile](https://developer.kameleo.io/integrations/puppeteer/#1-create-a-profile)
* [2\. Start the profile (customization point)](https://developer.kameleo.io/integrations/puppeteer/#2-start-the-profile-customization-point)
* [3\. Connect Puppeteer (Chroma only)](https://developer.kameleo.io/integrations/puppeteer/#3-connect-puppeteer-chroma-only)
* [4\. Run Puppeteer commands](https://developer.kameleo.io/integrations/puppeteer/#4-run-puppeteer-commands)
* [Option 2: Auto-start the profile (simpler)](https://developer.kameleo.io/integrations/puppeteer/#option-2-auto-start-the-profile-simpler)
* [1\. Create the profile (same as before, no start call later)](https://developer.kameleo.io/integrations/puppeteer/#1-create-the-profile-same-as-before-no-start-call-later)
* [Cleanup (stop, export, delete)](https://developer.kameleo.io/integrations/puppeteer/#cleanup-stop-export-delete)
* [Stop, export, or delete](https://developer.kameleo.io/integrations/puppeteer/#stop-export-or-delete)
* [Full examples on GitHub](https://developer.kameleo.io/integrations/puppeteer/#full-examples-on-github)
⌘K
---
# Import & export cookies | Kameleo Developer Center
Import & export cookies
Copy
===================================
In this tutorial you will learn how to list, add, update, and delete cookies of a Kameleo browser profile using the Local API SDKs. This lets you preserve or reset authenticated sessions programmatically.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app running locally (`http://localhost:5050`)
##### Sensitive data
Cookies can contain session IDs, refresh tokens, or tracking data. Never store them unencrypted or commit them to source control. Limit file system permissions.
1\. Create & start a profile, then gather cookies
-------------------------------------------------
Navigate a few high‑traffic sites to accumulate cookies, then stop the profile so you can manipulate them. Cookies can be listed, modified, or deleted only after the profile is terminated.
[Python](https://developer.kameleo.io/tutorials/import-export-cookies/#python)
[JavaScript](https://developer.kameleo.io/tutorials/import-export-cookies/#javascript)
[C#](https://developer.kameleo.io/tutorials/import-export-cookies/#c)
`from kameleo.local_api_client.models import CreateProfileRequest, CookieRequest from selenium import webdriver import time, os fingerprints = client.fingerprint.search_fingerprints(browser_product='firefox') profile = client.profile.create_profile(CreateProfileRequest(fingerprint_id=fingerprints[0].id, name='cookie tutorial')) opts = webdriver.FirefoxOptions() opts.set_capability('kameleo:profileId', profile.id) driver = webdriver.Remote(command_executor=f"http://localhost:{os.getenv('KAMELEO_PORT', '5050')}/webdriver", options=opts) for url in ['https://www.nytimes.com', 'https://whoer.net', 'https://www.youtube.com']: driver.get(url) time.sleep(5) client.profile.stop_profile(profile.id)`
2\. List cookies
----------------
Listing lets you choose which cookie to update or duplicate.
[Python](https://developer.kameleo.io/tutorials/import-export-cookies/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/import-export-cookies/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/import-export-cookies/#c-1)
`cookie_list = client.cookie.list_cookies(profile.id) for c in cookie_list[:5]: print(c.domain, c.name, c.value[:20])`
3\. Add a new cookie
--------------------
Ensure domain/path match the target site you will later visit; secure/httponly/samesite settings should reflect the intended usage.
[Python](https://developer.kameleo.io/tutorials/import-export-cookies/#python-2)
[JavaScript](https://developer.kameleo.io/tutorials/import-export-cookies/#javascript-2)
[C#](https://developer.kameleo.io/tutorials/import-export-cookies/#c-2)
`new_cookie = CookieRequest( domain='.example.com', name='custom_flag', value='enabled', path='/', secure=True, http_only=False, host_only=False, same_site='Lax' ) client.cookie.add_cookies(profile.id, [new_cookie]) print('Added new cookie custom_flag')`
4\. Update an existing cookie
-----------------------------
Select a cookie, modify its value, and re-add it via the same add API (it overwrites by name+domain+path).
[Python](https://developer.kameleo.io/tutorials/import-export-cookies/#python-3)
[JavaScript](https://developer.kameleo.io/tutorials/import-export-cookies/#javascript-3)
[C#](https://developer.kameleo.io/tutorials/import-export-cookies/#c-3)
`original = cookie_list[0] updated = CookieRequest(domain=original.domain, name=original.name, path=original.path, value='123', host_only=original.host_only, http_only=original.http_only, secure=original.secure, same_site=original.same_site, expiration_date=original.expiration_date) client.cookie.add_cookies(profile.id, [updated]) print(f'Updated cookie {original.name} -> 123')`
5\. Delete all cookies
----------------------
Use this to force a full logout / session reset while keeping other profile state (extensions, local storage, etc.).
[Python](https://developer.kameleo.io/tutorials/import-export-cookies/#python-4)
[JavaScript](https://developer.kameleo.io/tutorials/import-export-cookies/#javascript-4)
[C#](https://developer.kameleo.io/tutorials/import-export-cookies/#c-4)
`client.cookie.delete_cookies(profile.id) print('Deleted all cookies')`
6\. (Optional) Restart to verify
--------------------------------
Start the profile again and inspect cookies in DevTools or list them once more via the API; added values should appear (unless domain mismatch) and deletions should persist.
[On this page](https://developer.kameleo.io/tutorials/import-export-cookies/)
* [Prerequisites](https://developer.kameleo.io/tutorials/import-export-cookies/#prerequisites)
* [1\. Create & start a profile, then gather cookies](https://developer.kameleo.io/tutorials/import-export-cookies/#1-create--start-a-profile-then-gather-cookies)
* [2\. List cookies](https://developer.kameleo.io/tutorials/import-export-cookies/#2-list-cookies)
* [3\. Add a new cookie](https://developer.kameleo.io/tutorials/import-export-cookies/#3-add-a-new-cookie)
* [4\. Update an existing cookie](https://developer.kameleo.io/tutorials/import-export-cookies/#4-update-an-existing-cookie)
* [5\. Delete all cookies](https://developer.kameleo.io/tutorials/import-export-cookies/#5-delete-all-cookies)
* [6\. (Optional) Restart to verify](https://developer.kameleo.io/tutorials/import-export-cookies/#6-optional-restart-to-verify)
⌘K
---
# Pass command-line switches | Kameleo Developer Center
Pass command-line switches
Copy
======================================
In this tutorial you will add extra command-line switches to Chroma and Junglefox launches while keeping the coordinated fingerprint intact and avoiding blocked or redundant flags.
##### Note
You can't set the start page by passing a URL as an argument. Use the `startPage` property when creating or updating the profile; only pass feature flags as command-line switches.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* An existing profile
* Local API running (default: [http://localhost:5050](http://localhost:5050/)
)
1\. Launch a profile with extra arguments
-----------------------------------------
Start a profile while adding a couple of benign switches.
[Python](https://developer.kameleo.io/tutorials/passing-command-line-switches/#python)
[JavaScript](https://developer.kameleo.io/tutorials/passing-command-line-switches/#javascript)
[C#](https://developer.kameleo.io/tutorials/passing-command-line-switches/#c)
`from kameleo.local_api_client.models import BrowserSettings client.profile.start_profile(profile_id, BrowserSettings( arguments=[ '--disable-notifications', '--mute-audio' ] )) print('Started profile with custom arguments')`
If any supplied switch is blacklisted, Kameleo returns an error explaining which argument is incompatible.
2\. Blacklisted switches
------------------------
Some native browser switches are blocked to preserve fingerprint integrity and avoid conflicts. See the full list: [Blacklisted browser switches](https://developer.kameleo.io/reference/blacklisted-browser-switches/)
.
3\. Full references
-------------------
For comprehensive lists of native browser command line options, see:
* Chroma: [https://peter.sh/experiments/chromium-command-line-switches/](https://peter.sh/experiments/chromium-command-line-switches/)
* Junglefox: [https://wiki.mozilla.org/Firefox/CommandLineOptions](https://wiki.mozilla.org/Firefox/CommandLineOptions)
[On this page](https://developer.kameleo.io/tutorials/passing-command-line-switches/)
* [Prerequisites](https://developer.kameleo.io/tutorials/passing-command-line-switches/#prerequisites)
* [1\. Launch a profile with extra arguments](https://developer.kameleo.io/tutorials/passing-command-line-switches/#1-launch-a-profile-with-extra-arguments)
* [2\. Blacklisted switches](https://developer.kameleo.io/tutorials/passing-command-line-switches/#2-blacklisted-switches)
* [3\. Full references](https://developer.kameleo.io/tutorials/passing-command-line-switches/#3-full-references)
⌘K
---
# Emulate mobile devices | Kameleo Developer Center
Emulate mobile devices
Copy
==================================
Learn how to spin up a real mobile browser profile (iOS or Android), start it, tune the key mobile emulation options, and drive it with Selenium / WebDriver.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app running locally (default `http://localhost:5050`)
1\. Search for a mobile fingerprint
-----------------------------------
We query deviceType `mobile` and narrow to an iOS + Safari fingerprint (change to Android/Chrome if you prefer). Pick the first match for simplicity.
[Python](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#python)
[JavaScript](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#javascript)
[C#](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#c)
`fingerprints = client.fingerprint.search_fingerprints( device_type='mobile', os_family='ios', browser_product='safari' ) fingerprint = fingerprints[0] print('Selected fingerprint:', fingerprint.id)`
2\. Create the mobile profile
-----------------------------
Create a profile from the chosen fingerprint. Kameleo will apply recommended settings automatically.
[Python](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#c-1)
`from kameleo.local_api_client.models import CreateProfileRequest create_req = CreateProfileRequest( fingerprint_id=fingerprint.id, name='automate mobile profiles on desktop example' ) profile = client.profile.create_profile(create_req) print('Created profile', profile.id)`
3\. Start the profile with additional options
---------------------------------------------
When starting a mobile profile you can send Kameleo specific additionalOptions.
##### Touch vs. mouse clicks
If your automation scripts hang after performing a click in a mobile profile, first try starting with disableTouchEmulation=true. Once stable, re‑enable touch emulation only if you specifically need touch events (e.g., gesture testing).
Key options covered here:
* **disableTouchEmulation (boolean):** If true, Kameleo will NOT enable Chrome touch emulation. Default behavior (option absent or false) enables touch events for a realistic mobile environment. Some automation frameworks (or test code written with desktop assumptions) may stall on clicks when touch emulation is active; setting this to true restores pure mouse semantics for reliability.
* **deviceScaleFactor (number, optional):** Overrides the device pixel ratio provided by the selected fingerprint. If omitted, the fingerprint’s native DPR is used (e.g., often 3 on newer iPhones, 2 on many Android devices, 1 on low‑density displays).
You can supply one or both via the additionalOptions array. Below we always disable touch emulation and (optionally) show how to force a different deviceScaleFactor.
[Python](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#python-2)
[JavaScript](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#javascript-2)
[C#](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#c-2)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( additional_options=[ Preference(key='disableTouchEmulation', value=True), # Preference(key='deviceScaleFactor', value=3), # Uncomment to override the value coming from the fingerprint ] )) print('Profile started (touch emulation disabled)')`
4\. Automate with Selenium
--------------------------
Connect to the running browser and perform a simple Wikipedia search. The profile is already mobile: viewport metrics, user agent, and other signals reflect the selected fingerprint (and your optional overrides).
[Python](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#python-3)
[JavaScript](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#javascript-3)
[C#](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#c-3)
`from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time options = webdriver.ChromeOptions() options.set_capability('kameleo:profileId', profile.id) driver = webdriver.Remote( command_executor='http://localhost:5050/webdriver', options=options ) driver.get('https://wikipedia.org') driver.find_element(By.NAME, 'search').send_keys('Chameleon', Keys.ENTER) WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'content'))) print('Title:', driver.title) time.sleep(5) client.profile.stop_profile(profile.id)`
Troubleshooting
---------------
* Click actions hang or timeout: Start with disableTouchEmulation=true.
* Elements appear too large/small: Adjust deviceScaleFactor (try 1, 2, or 3).
* Site serves desktop layout: Confirm you selected a mobile fingerprint (deviceType mobile) and did not disable other mobile signals.
* WebDriver cannot connect: Ensure the profile actually started and that `/webdriver` endpoint matches the configured port.
[On this page](https://developer.kameleo.io/tutorials/emulating-mobile-devices/)
* [Prerequisites](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#prerequisites)
* [1\. Search for a mobile fingerprint](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#1-search-for-a-mobile-fingerprint)
* [2\. Create the mobile profile](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#2-create-the-mobile-profile)
* [3\. Start the profile with additional options](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#3-start-the-profile-with-additional-options)
* [4\. Automate with Selenium](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#4-automate-with-selenium)
* [Troubleshooting](https://developer.kameleo.io/tutorials/emulating-mobile-devices/#troubleshooting)
⌘K
---
# Manage profiles | Kameleo Developer Center
Manage profiles
Copy
===========================
In this tutorial you will walk through the full lifecycle of a browser profile: search a fingerprint, create a profile, start and stop it, update settings (add a proxy), duplicate via export/import, and finally delete it when no longer needed.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app running locally (`http://localhost:5050`)
1\. Search a fingerprint
------------------------
Pick a recent desktop Chrome fingerprint (adjust filters as needed). Limit filtering at first, then narrow.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c)
`fps = client.fingerprint.search_fingerprints( device_type='desktop', browser_product='chrome', ) fingerprint = fps[0] print('Selected fingerprint:', fingerprint.id)`
2\. Create the profile
----------------------
Below is a full example showing every configurable field of the profile creation request. In real use you often only set `fingerprintId`, `name`, maybe `language`, `proxy`, and a couple of masking overrides. Leave any field out to accept the default inferred from the fingerprint.
##### Full option reference
For the exhaustive list of allowed values, defaults, and schema details, consult the OpenAPI specification in the [API reference](https://developer.kameleo.io/reference/api-reference/)
.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-1)
`from kameleo.local_api_client.models import ( CreateProfileRequest, TimezoneChoice, GeolocationChoice, ProxyChoice, Server, WebRtcChoice, ScreenChoice, ScreenSize, HardwareConcurrencyChoice, DeviceMemoryChoice, WebglMetaChoice, WebglMetaValue, TimezoneSpoofingType, GeolocationSpoofingType, WebRtcSpoofingType, ScreenSpoofingType, HardwareConcurrencySpoofingType, DeviceMemorySpoofingType, ProxyConnectionType, WebglMetaSpoofingType ) # Full request showcasing every available field. Omit fields you don't need. create_req = CreateProfileRequest( fingerprint_id=fingerprint.id, name='acct-main', folder_id=None, tags=['marketing', 'facebook'], canvas='intelligent', webgl='noise', webgl_meta=WebglMetaChoice( value=WebglMetaSpoofingType.MANUAL, extra=WebglMetaValue(vendor='Intel Inc.', renderer='Intel Iris OpenGL Engine') ), audio='noise', timezone=TimezoneChoice(value=TimezoneSpoofingType.MANUAL, extra='Europe/Berlin'), geolocation=GeolocationChoice(value=GeolocationSpoofingType.MANUAL, extra={'latitude': 52.52, 'longitude': 13.405, 'accuracy': 10}), proxy=ProxyChoice(value=ProxyConnectionType.HTTP, extra=Server(host='proxy.example', port=8000, id='user', secret='pass')), web_rtc=WebRtcChoice(value=WebRtcSpoofingType.MANUAL, extra={'localIp': '10.0.0.5', 'publicIp': '93.184.216.34'}), fonts='automatic', screen=ScreenChoice(value=ScreenSpoofingType.MANUAL, extra=ScreenSize(width=1920, height=1080)), hardware_concurrency=HardwareConcurrencyChoice(value=HardwareConcurrencySpoofingType.MANUAL, extra=8), device_memory=DeviceMemoryChoice(value=DeviceMemorySpoofingType.MANUAL, extra=8), language='en-US,en', start_page='https://whoer.net/', password_manager='enabled', extensions=['/absolute/path/extension.crx'], notes='I used this profile for affiliate marketing.', storage='local' ) profile = client.profile.create_profile(create_req) print('Created profile', profile.id)`
3\. Start and stop the profile
------------------------------
Only start when you are ready to automate. Stop to free resources; the session state (cookies, storage) is preserved.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-2)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-2)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-2)
`client.profile.start_profile(profile.id) print('Profile started') client.profile.stop_profile(profile.id) print('Profile stopped')`
4\. List profiles with filtering by lifetime state
--------------------------------------------------
After creating and starting profiles, you may want to list them and filter by their current lifetime state. Profiles can be in one of several states: `created`, `starting`, `running`, `terminating`, `terminated`, `locked`, `loading`, or `unknown`. Filtering by state helps monitor which profiles are active and manage resources efficiently.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-3)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-3)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-3)
`from kameleo.local_api_client.models import ProfileLifetimeState # List all profiles all_profiles = client.profile.list_profiles() print(f'Total profiles: {len(all_profiles)}') # Filter for running profiles only running_profiles = client.profile.list_profiles(ProfileLifetimeState.RUNNING) print(f'Running profiles: {len(running_profiles)}') for p in running_profiles: print(f' - {p.name} (ID: {p.id})') # Filter for terminated profiles (stopped but previously started) terminated_profiles = client.profile.list_profiles(ProfileLifetimeState.TERMINATED) print(f'Terminated profiles: {len(terminated_profiles)}') for p in terminated_profiles: print(f' - {p.name} (ID: {p.id})') # Filter for newly created profiles (never started) created_profiles = client.profile.list_profiles(ProfileLifetimeState.CREATED) print(f'Created profiles: {len(created_profiles)}')`
##### Available lifetime states
The complete list of profile lifetime states includes: `created` (profile created but never started), `starting` (browser engine starting), `running` (browser active), `terminating` (browser shutting down), `terminated` (browser stopped but was running before), `locked` (in use by another user), `loading` (syncing with cloud storage), and `unknown` (undefined state). Filter by only one state per API call.
5\. Update settings (add a proxy)
---------------------------------
Updates require the profile to be in a stopped (terminated) state. Attempting to change network settings while running can fail or cause instability.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-4)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-4)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-4)
`from kameleo.local_api_client.models import ProxyChoice, Server, UpdateProfileRequest, ProxyConnectionType update_req = UpdateProfileRequest(proxy=ProxyChoice(value=ProxyConnectionType.HTTP, extra=Server(host='proxy.example', port=8000, id='u', secret='p'))) updated = client.profile.update_profile(profile.id, update_profile_request=update_req) print('Proxy set to', updated.proxy.value)`
6\. Export and import (backup / restore)
----------------------------------------
Export creates a portable archive (.kameleo) of the existing profile (including settings, storage, cookies, history, bookmarks, extensions). Importing restores that exact profile (same profile ID). Import will fail if a profile with the same ID is already loaded.
##### Import behavior
Export/Import preserves the original profile ID. To create a second independent copy with a new ID use the Duplicate method instead.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-5)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-5)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-5)
`# Ensure the profile is stopped, then back it up from kameleo.local_api_client.models import ExportProfileRequest, ImportProfileRequest client.profile.stop_profile(profile.id) client.profile.export_profile(profile.id, export_profile_request=ExportProfileRequest(path='./acct-main.kameleo')) print('Exported profile to acct-main.kameleo') # Remove (or move to another machine) before restoring; import will fail if same ID is still loaded client.profile.delete_profile(profile.id) restored = client.profile.import_profile(import_profile_request=ImportProfileRequest(path='./acct-main.kameleo')) print('Restored profile with SAME ID', restored.id)`
7\. Upgrade the profile (browser/kernel)
----------------------------------------
Keep profiles current to benefit from the latest browser security patches, modern TLS/cipher suites, and widely distributed real‑world fingerprints. Upgrading refreshes the profile's fingerprint to the newest matching browser version and (if applicable) switches to a better fitting kernel. The profile ID, local storage (cookies, history, etc.), and your settings remain; only the browser fingerprinting surface changes.
##### Fingerprint changes
Upgrading alters the browser version and related fingerprint fields. If a site correlates prior visits with the old version, a sudden jump might look suspicious. Prefer upgrading right after creation or during a maintenance window, not mid critical automation flow.
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-6)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-6)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-6)
`# Ensure the profile is stopped before upgrading client.profile.stop_profile(profile.id) upgraded = client.profile.upgrade_profile_kernel(profile.id) print('Upgraded browser to', upgraded.fingerprint.browser.product, upgraded.fingerprint.browser.version)`
8\. Delete when finished
------------------------
Remove profiles you no longer need to keep the workspace clean and reclaim disk space (profiles store cached browsing data, extensions, cookies, history, and other artifacts).
[Python](https://developer.kameleo.io/tutorials/managing-profiles/#python-7)
[JavaScript](https://developer.kameleo.io/tutorials/managing-profiles/#javascript-7)
[C#](https://developer.kameleo.io/tutorials/managing-profiles/#c-7)
`client.profile.delete_profile(profile.id) print('Deleted original profile')`
[On this page](https://developer.kameleo.io/tutorials/managing-profiles/)
* [Prerequisites](https://developer.kameleo.io/tutorials/managing-profiles/#prerequisites)
* [1\. Search a fingerprint](https://developer.kameleo.io/tutorials/managing-profiles/#1-search-a-fingerprint)
* [2\. Create the profile](https://developer.kameleo.io/tutorials/managing-profiles/#2-create-the-profile)
* [3\. Start and stop the profile](https://developer.kameleo.io/tutorials/managing-profiles/#3-start-and-stop-the-profile)
* [4\. List profiles with filtering by lifetime state](https://developer.kameleo.io/tutorials/managing-profiles/#4-list-profiles-with-filtering-by-lifetime-state)
* [5\. Update settings (add a proxy)](https://developer.kameleo.io/tutorials/managing-profiles/#5-update-settings-add-a-proxy)
* [6\. Export and import (backup / restore)](https://developer.kameleo.io/tutorials/managing-profiles/#6-export-and-import-backup--restore)
* [7\. Upgrade the profile (browser/kernel)](https://developer.kameleo.io/tutorials/managing-profiles/#7-upgrade-the-profile-browserkernel)
* [8\. Delete when finished](https://developer.kameleo.io/tutorials/managing-profiles/#8-delete-when-finished)
⌘K
---
# Using proxy servers | Kameleo Developer Center
Using proxy servers
Copy
===============================
You will create a new profile with a SOCKS5 proxy, verify that the proxy works, change it to an HTTP proxy, then remove the proxy entirely. The flow is identical across all SDKs; code samples are provided for Python, JavaScript, and C#.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app is running locally (default API base URL: `http://localhost:5050`).
* Network access to the local API port (no firewall blocking 5050).
* Access to at least one working proxy server (HTTP, HTTPS, SOCKS5, or SSH) with host, port, and credentials if required.
1\. Create a profile with a proxy
---------------------------------
Select a fingerprint and attach a proxy at creation. Provide credentials only when required by your provider.
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c)
`from kameleo.local_api_client.models import CreateProfileRequest, ProxyChoice, Server fps = client.fingerprint.search_fingerprints(browser_product='chrome') profile = client.profile.create_profile(CreateProfileRequest( fingerprint_id=fps[0].id, name='proxy tutorial', proxy=ProxyChoice( value='socks5', extra=Server(host='1.2.3.4', port=1080, id='user', secret='pass') ) )) print('Created profile with proxy:', profile.id, profile.proxy.value)`
Kameleo tests the proxy before launching the profile. If the test fails, the browser does not start.
2\. Test the proxy connection
-----------------------------
Check that the proxy you just attached actually works, before you start the browser. The profile keeps the credentials, so you only pass its id.
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-1)
`result = client.profile.test_profile_proxy(profile.id) print('Proxy test result:', result.result) for step in result.steps: print(step.name, '->', 'ok' if step.successful else step.comment)`
### Interpret the result
The response carries an overall `result` and the list of `steps` that were executed.
| Result | Meaning |
| --- | --- |
| `success` | Every step passed. |
| `partial_success` | The website was reachable over at least one of IPv4, IPv6, or DNS name, and the IP location lookup succeeded. |
| `failure` | None of the connectivity checks succeeded. |
Treat `partial_success` as usable but degraded. It commonly means the proxy has no IPv6 route, which is fine for most targets.
A `failure` result arrives as a `503` error response instead of a normal one, so the SDKs raise an exception rather than returning it. Wrap the call in a try/catch if you want to handle an unusable proxy yourself.
Each entry in `steps` carries a `step` identifier, a human-readable `name`, a `successful` flag, and a `comment` holding the error message when the step failed.
| Step | Checks |
| --- | --- |
| `ssh_connection` | Connection to the proxy server. SSH proxies only. |
| `direct_ping` | Direct internet connectivity, bypassing the proxy. |
| `direct_https` | Direct HTTPS connectivity, bypassing the proxy. |
| `proxy_ipv4` | IPv4 connectivity through the proxy. |
| `proxy_ipv6` | IPv6 connectivity through the proxy. |
| `proxy_website` | HTTPS connectivity to a website through the proxy. |
| `proxy_location` | Geographic location lookup of the proxy IP address. |
##### Note
The `direct_*` steps do not use the proxy. When they fail there is a problem with your internet connection, not with the proxy.
### Test a proxy without a profile
You do not need a profile to run the test. Pass the connection settings directly when you want to check a proxy before committing to it, for example while picking a working one out of a pool. Nothing is stored and the response is identical to the one above.
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-2)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-2)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-2)
`from kameleo.local_api_client.models import TestProxyRequest, ProxyChoice, Server result = client.general.test_proxy(TestProxyRequest( proxy=ProxyChoice( value='socks5', extra=Server(host='1.2.3.4', port=1080, id='user', secret='pass') ) )) print('Proxy test result:', result.result)`
3\. Update the proxy
--------------------
Stop the profile before changing proxy settings (rotation mid-session can cause network anomalies and is not supported).
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-3)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-3)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-3)
`client.profile.stop_profile(profile.id) updated = client.profile.update_profile(profile.id, update_profile_request={ 'proxy': ProxyChoice(value='http', extra=Server(host='proxy.host', port=8000)) }) print('Updated proxy to', updated.proxy.value)`
4\. Remove the proxy
--------------------
Set the proxy to null (or omit the field) to revert to a direct connection.
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-4)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-4)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-4)
`removed = client.profile.update_profile(profile.id, update_profile_request={ 'proxy': None }) print('Proxy removed, value now:', removed.proxy)`
5\. Configure proxy bypass (optional)
-------------------------------------
Some destinations do not need to go through your proxy. Bypassing them reduces proxy bandwidth usage and lowers costs. Common candidates include CDN hosts serving static assets (images, fonts, scripts), video streaming domains, and internal services. Configure a bypass list so those hosts connect directly while the rest of the traffic uses the proxy.
Kameleo automatically adds its own loopback endpoints. You only provide the additional hosts or CIDR ranges. The mechanism differs per kernel:
* Chroma: supply an extra command-line switch `--proxy-bypass-list` with a semicolon-separated list.
* Junglefox: set the preference `network.proxy.no_proxies_on` with a comma-separated list.
### Chroma example
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-5)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-5)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-5)
`from kameleo.local_api_client.models import BrowserSettings client.profile.start_profile(profile_id, BrowserSettings( arguments=[ '--proxy-bypass-list=*.internal.local;192.168.0.0/16' ] ))`
### Junglefox example
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-6)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-6)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-6)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile_id, BrowserSettings( preferences=[ Preference(key='network.proxy.no_proxies_on', value='intranet.local,cdn.example.com:443') ] ))`
Guidelines:
* Keep the list minimal; every pattern incurs a small matching cost.
* Use CIDR for subnets instead of enumerating many hosts.
* Avoid bypassing domains that perform geo or security checks; you may expose differing IP behavior.
* Remember that bypass applies to all schemes (HTTP/HTTPS/WebSocket) for those hosts.
6\. Limit WebRTC to proxied TCP (optional)
------------------------------------------
Kameleo automatically masks your WebRTC IP address to match your proxy IP. However, WebRTC can still leak your real IP through non-proxied UDP connections because browsers do not route UDP traffic through HTTP/SOCKS proxies by default, and some proxy providers do not support UDP traffic at all.
To prevent IP leaks, configure the browser to only allow WebRTC connections over TCP that go through your proxy. The mechanism differs per kernel:
* Chroma: set the preference `webrtc.ip_handling_policy` to `disable_non_proxied_udp`.
* Junglefox: set the preference `media.peerconnection.ice.proxy_only` to `true`.
### Chroma example
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-7)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-7)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-7)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( preferences=[ Preference(key="webrtc.ip_handling_policy", value="disable_non_proxied_udp") ] ))`
See more details: [Chrome's WebRTC IP handling policy](https://chromeenterprise.google/policies/web-rtc-ip-handling/)
.
### Junglefox example
[Python](https://developer.kameleo.io/tutorials/using-proxy-servers/#python-8)
[JavaScript](https://developer.kameleo.io/tutorials/using-proxy-servers/#javascript-8)
[C#](https://developer.kameleo.io/tutorials/using-proxy-servers/#c-8)
`from kameleo.local_api_client.models import BrowserSettings, Preference client.profile.start_profile(profile.id, BrowserSettings( preferences=[ Preference(key="media.peerconnection.ice.proxy_only", value=True) ] ))`
7\. Best practices
------------------
* Match proxy country with fingerprint locale and language.
* Rotate failing residential proxies; monitor connection error rate.
* Keep a warm pool of tested proxies to reduce startup latency.
* Avoid switching IP mid-session to prevent extra security or re-auth challenges.
[On this page](https://developer.kameleo.io/tutorials/using-proxy-servers/)
* [Prerequisites](https://developer.kameleo.io/tutorials/using-proxy-servers/#prerequisites)
* [1\. Create a profile with a proxy](https://developer.kameleo.io/tutorials/using-proxy-servers/#1-create-a-profile-with-a-proxy)
* [2\. Test the proxy connection](https://developer.kameleo.io/tutorials/using-proxy-servers/#2-test-the-proxy-connection)
* [Interpret the result](https://developer.kameleo.io/tutorials/using-proxy-servers/#interpret-the-result)
* [Test a proxy without a profile](https://developer.kameleo.io/tutorials/using-proxy-servers/#test-a-proxy-without-a-profile)
* [3\. Update the proxy](https://developer.kameleo.io/tutorials/using-proxy-servers/#3-update-the-proxy)
* [4\. Remove the proxy](https://developer.kameleo.io/tutorials/using-proxy-servers/#4-remove-the-proxy)
* [5\. Configure proxy bypass (optional)](https://developer.kameleo.io/tutorials/using-proxy-servers/#5-configure-proxy-bypass-optional)
* [Chroma example](https://developer.kameleo.io/tutorials/using-proxy-servers/#chroma-example)
* [Junglefox example](https://developer.kameleo.io/tutorials/using-proxy-servers/#junglefox-example)
* [6\. Limit WebRTC to proxied TCP (optional)](https://developer.kameleo.io/tutorials/using-proxy-servers/#6-limit-webrtc-to-proxied-tcp-optional)
* [Chroma example](https://developer.kameleo.io/tutorials/using-proxy-servers/#chroma-example-1)
* [Junglefox example](https://developer.kameleo.io/tutorials/using-proxy-servers/#junglefox-example-1)
* [7\. Best practices](https://developer.kameleo.io/tutorials/using-proxy-servers/#7-best-practices)
⌘K
---
# Install browser extensions | Kameleo Developer Center
Install browser extensions
Copy
======================================
In this tutorial you will attach extensions to a profile at creation, add more later, and understand how persistence and compatibility work. Extensions can enhance automation (ad blocking, helper tooling) but must not conflict with fingerprint masking.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app running locally (default `http://localhost:5050`)
* Local file paths to valid extension packages (`.crx` for Chromium, `.xpi` for Firefox)
##### Avoid masking overlap
Do not install extensions that alter user agent, canvas, WebGL, timezone, or language. They may create inconsistencies versus Kameleo's coordinated fingerprint.
1\. Add extensions at profile creation
--------------------------------------
[Python](https://developer.kameleo.io/tutorials/install-browser-extensions/#python)
[JavaScript](https://developer.kameleo.io/tutorials/install-browser-extensions/#javascript)
[C#](https://developer.kameleo.io/tutorials/install-browser-extensions/#c)
`from kameleo.local_api_client.models import CreateProfileRequest, UpdateProfileRequest fp = client.fingerprint.search_fingerprints(browser_product='chrome')[0] profile = client.profile.create_profile( CreateProfileRequest( fingerprint_id=fp.id, name='with-extensions', extensions=['/Users/me/exts/uBlock.crx', '/Users/me/exts/helper.xpi'], ) ) print('Created profile with extensions', profile.id)`
2\. Add extensions after creation
---------------------------------
[Python](https://developer.kameleo.io/tutorials/install-browser-extensions/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/install-browser-extensions/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/install-browser-extensions/#c-1)
`current = profile.extensions or [] update = UpdateProfileRequest(extensions=current + ['/Users/me/exts/newTool.crx']) updated = client.profile.update_profile(profile.id, update_profile_request=update) print('Extensions now:', updated.extensions)`
3\. Persistence & export
------------------------
* Extensions and their storage persist while the profile exists
* Exported profile archives (.kameleo) include installed extensions
* Importing the archive restores them automatically
4\. Troubleshooting
-------------------
| Issue | Resolution |
| --- | --- |
| Extension missing on start | Confirm path exists and has correct file extension (.crx/.xpi). |
| Browser slow to launch | Large extensions: remove unnecessary ones or profile separately. |
| Fingerprint mismatch alerts | Remove spoofing extensions that overlap with Kameleo masking. |
[On this page](https://developer.kameleo.io/tutorials/install-browser-extensions/)
* [Prerequisites](https://developer.kameleo.io/tutorials/install-browser-extensions/#prerequisites)
* [1\. Add extensions at profile creation](https://developer.kameleo.io/tutorials/install-browser-extensions/#1-add-extensions-at-profile-creation)
* [2\. Add extensions after creation](https://developer.kameleo.io/tutorials/install-browser-extensions/#2-add-extensions-after-creation)
* [3\. Persistence & export](https://developer.kameleo.io/tutorials/install-browser-extensions/#3-persistence--export)
* [4\. Troubleshooting](https://developer.kameleo.io/tutorials/install-browser-extensions/#4-troubleshooting)
⌘K
---
# Start headless browsers | Kameleo Developer Center
Start headless browsers
Copy
===================================
In this tutorial you will launch Chroma (Chromium-based) and Junglefox (Firefox-based) profiles in headless mode, choose the correct flags, and balance performance with detection resilience.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* ID of an existing profile that is currently stopped
* Local API running (default: [http://localhost:5050](http://localhost:5050/)
)
1\. Start Chroma headless
-------------------------
Use `--headless` for Chroma. Current Chroma builds map this to the modern headless mode automatically; you no longer need the historical `--headless=new` variant. If you need deeper Chromium implementation detail, see the official Chrome headless guide: [https://developer.chrome.com/docs/chromium/headless](https://developer.chrome.com/docs/chromium/headless)
.
[Python](https://developer.kameleo.io/tutorials/starting-headless-browsers/#python)
[JavaScript](https://developer.kameleo.io/tutorials/starting-headless-browsers/#javascript)
[C#](https://developer.kameleo.io/tutorials/starting-headless-browsers/#c)
`from kameleo.local_api_client.models import BrowserSettings client.profile.start_profile(profile.id, BrowserSettings( arguments=['--headless'] )) print('Started Chroma headless')`
2\. Start Junglefox headless
----------------------------
Firefox (Junglefox) uses the single-dash `-headless` flag. Keep arguments minimal; masking already supplies coordinated feature settings. For more background on Firefox headless behavior, consult Mozilla's article: [https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/](https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/)
.
[Python](https://developer.kameleo.io/tutorials/starting-headless-browsers/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/starting-headless-browsers/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/starting-headless-browsers/#c-1)
`from kameleo.local_api_client.models import BrowserSettings client.profile.start_profile(profile_id, BrowserSettings( arguments=['-headless'] )) print('Started Junglefox headless')`
3\. More information
--------------------
If you need to dive deeper into native browser headless capabilities or limitations, refer to the upstream documentation:
* Chromium headless: [https://developer.chrome.com/docs/chromium/headless](https://developer.chrome.com/docs/chromium/headless)
* Firefox headless: [https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/](https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/)
[On this page](https://developer.kameleo.io/tutorials/starting-headless-browsers/)
* [Prerequisites](https://developer.kameleo.io/tutorials/starting-headless-browsers/#prerequisites)
* [1\. Start Chroma headless](https://developer.kameleo.io/tutorials/starting-headless-browsers/#1-start-chroma-headless)
* [2\. Start Junglefox headless](https://developer.kameleo.io/tutorials/starting-headless-browsers/#2-start-junglefox-headless)
* [3\. More information](https://developer.kameleo.io/tutorials/starting-headless-browsers/#3-more-information)
⌘K
---
# Usage limits | Kameleo Developer Center
Usage limits
Copy
========================
Every Kameleo plan enforces the usage limits described on this page. Both limits are aggregated per team, not per device or user.
Concurrent browser limits
-------------------------
Your plan limits how many profiles can run at the same time. This is tracked as two independent quotas: one for all profiles regardless of device type, and one specifically for mobile profiles.
| Quota | Counted as | Error code when exceeded |
| --- | --- | --- |
| Concurrent Browsers (CB) | Total profiles of any device type running at once. | `running_profiles_limit_reached` |
| Mobile Concurrent Browsers | Currently running mobile profiles. Starting a mobile profile counts against both CB and mobile CB. | `running_mobile_profiles_limit_reached` |
### Plan limits
The exact CB and mobile CB limits depend on your active plan. See the [pricing page](https://kameleo.io/pricing)
for a comparison of limits across plans.
### Checking current usage
Current CB usage is visible in the Kameleo app's bottom-left corner, hover over it to see mobile CB usage in a tooltip. Both sync in real time across all team members. It's also available via the `GetUserInfo` endpoint, see the [API reference](https://developer.kameleo.io/reference/api-reference/)
for the full response schema.
API request rate limits
-----------------------
Your plan limits how many API requests the team can send per minute. Only the following high-impact endpoints count toward the limit:
* SearchFingerprints
* CreateProfile
* StartProfile
All other operations (e.g., stop profile, list profiles) are lightweight and do not count.
### Plan limits
The exact RPM limits depend on your active plan:
| Plan | Requests / minute (RPM) |
| --- | --- |
| Free | 60 |
| Startup | 120 |
| Business | 600 |
| Enterprise | 1200 |
### Checking current usage
There is currently no endpoint that reports current RPM usage. Exceeding the limit returns HTTP 429 with `rate_limit_exceeded` error code on further counted calls until usage falls back under the limit; see [API error handling](https://developer.kameleo.io/reference/api-error-handling/)
for the full reference.
FAQ
---
| Question | Answer |
| --- | --- |
| Are limits per device or per team? | Per team. All team members share the same CB, mobile CB, and RPM quotas. |
| Does creating or storing a profile count toward CB? | No. Only profiles that are actively running count. |
| Does stopping a profile count toward RPM? | No. Only `SearchFingerprints`, `CreateProfile`, and `StartProfile` are counted. |
| Can I get a higher limit? | Enterprise plans can contact support for a tailored allocation. |
[On this page](https://developer.kameleo.io/reference/usage-limits/)
* [Concurrent browser limits](https://developer.kameleo.io/reference/usage-limits/#concurrent-browser-limits)
* [Plan limits](https://developer.kameleo.io/reference/usage-limits/#plan-limits)
* [Checking current usage](https://developer.kameleo.io/reference/usage-limits/#checking-current-usage)
* [API request rate limits](https://developer.kameleo.io/reference/usage-limits/#api-request-rate-limits)
* [Plan limits](https://developer.kameleo.io/reference/usage-limits/#plan-limits-1)
* [Checking current usage](https://developer.kameleo.io/reference/usage-limits/#checking-current-usage-1)
* [FAQ](https://developer.kameleo.io/reference/usage-limits/#faq)
⌘K
---
# Disable closed shadow DOMs | Kameleo Developer Center
Disable closed shadow DOMs
Copy
======================================
This tutorial shows you how to force every closed shadow DOM on visited pages to open so your automation code can query inside without custom execution contexts. You'll enable the `forceOpenShadowRoot` feature, start a profile, validate it works, and learn the trade‑offs.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* Kameleo app is running locally (default API base URL: `http://localhost:5050`).
Understand the feature
----------------------
Modern web apps encapsulate DOM and styles in Shadow Roots. Closed shadow roots cannot be traversed via standard DOM APIs; you must call custom element methods. Kameleo can patch kernels to expose closed roots as if they were open, simplifying selectors for scraping, testing, and CAPTCHA widget handling.
##### Side effects
Opening all closed roots may: (1) expose implementation details sites rely on staying private, (2) cause fragile selectors if a site later restructures components. Use only when you specifically need access closed roots.
Option 1: Enable when starting a profile (SDKs)
-----------------------------------------------
Set `kameleo:forceOpenShadowRoot = true` in the browser start settings / request body when calling the start endpoint.
[Python](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#python)
[JavaScript](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#javascript)
[C#](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#c)
`from kameleo.local_api_client.models import BrowserSettings, Preference # Assume an existing profile object or create one beforehand client.profile.start_profile(profile.id, BrowserSettings( additional_options=[Preference(key='kameleo:forceOpenShadowRoot', value=True)] )) print('Profile started with forced open shadow roots')`
Option 2: Enable through Selenium WebDriver capability
------------------------------------------------------
Add the custom capability `kameleo:forceOpenShadowRoot: true` (alongside `kameleo:profileId`).
[Python](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#python-1)
[JavaScript](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#javascript-1)
[C#](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#c-1)
`from selenium import webdriver caps = { 'kameleo:profileId': profile_id, # existing profile id 'kameleo:forceOpenShadowRoot': True, 'browserName': 'Kameleo' } driver = webdriver.Remote(command_executor='http://localhost:5050/webdriver', desired_capabilities=caps)`
5\. Validate
------------
1. Navigate to a site known to use closed shadow roots (e.g., Cloudflare Turnstile).
2. Open DevTools Console and run:
`// All shadow roots should be accessible [...document.querySelectorAll("*")] .map((el) => el.shadowRoot) .filter((r) => r) .slice(0, 5);`
If objects are returned for components that normally have closed roots, the feature works.
6\. Troubleshooting
-------------------
| Symptom | Resolution |
| --- | --- |
| No additional roots accessible | Ensure you passed the option at start; stopping/restarting is required for changes. |
| Slower initial page load | Disable the option for profiles where it's not required. |
| Site scripts behave oddly | Try without the feature; some code may depend on closed encapsulation. |
[On this page](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/)
* [Prerequisites](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#prerequisites)
* [Understand the feature](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#understand-the-feature)
* [Option 1: Enable when starting a profile (SDKs)](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#option-1-enable-when-starting-a-profile-sdks)
* [Option 2: Enable through Selenium WebDriver capability](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#option-2-enable-through-selenium-webdriver-capability)
* [5\. Validate](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#5-validate)
* [6\. Troubleshooting](https://developer.kameleo.io/tutorials/disable-closed-shadow-doms/#6-troubleshooting)
⌘K
---
# Code examples | Kameleo Developer Center
Code examples
Copy
=========================
The [kameleo-io/kameleo](https://github.com/kameleo-io/kameleo)
GitHub repository contains a collection of self-contained, runnable examples for each SDK. Each example covers one specific task and can be cloned and run on its own. Topics include profile management, browser automation frameworks, proxy setup, and cookie handling.
##### Tip
If you are new to the API, start with the [Getting started](https://developer.kameleo.io/getting-started/quickstart/)
guide before exploring these examples.
| Example | Python | JavaScript | C# |
| --- | --- | --- | --- |
| Create, duplicate, update, and launch profiles via the API | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/basic_profile_operations/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/basic_profile_operations/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/basic_profile_operations/Program.cs) |
| Delete all profiles from your Kameleo workspace | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/clean_workspace/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/clean_workspace/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/clean_workspace/Program.cs) |
| Control a Chrome profile with Selenium over WebDriver | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_selenium/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_selenium/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_selenium/Program.cs) |
| Control a Chrome profile with Playwright via CDP | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_playwright_to_chrome/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_playwright_to_chrome/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_playwright_to_chrome/Program.cs) |
| Control a Firefox (Junglefox) profile with Playwright | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_playwright_to_firefox/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_playwright_to_firefox/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_playwright_to_firefox/Program.cs) |
| Control a Chrome profile with Puppeteer via CDP | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/connect_with_puppeteer/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/connect_with_puppeteer/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/connect_with_puppeteer/Program.cs) |
| Test a proxy, then attach it to a browser profile | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/start_with_proxy/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/start_with_proxy/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/start_with_proxy/Program.cs) |
| List, add, and delete cookies from a profile via the API | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/manage_cookies/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/manage_cookies/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/manage_cookies/Program.cs) |
| Warm up a profile by browsing real sites to collect cookies | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/cookie_robot/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/cookie_robot/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/cookie_robot/Program.cs) |
| Take a full-page screenshot of a website using Puppeteer | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/take_screenshot_with_puppeteer/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/take_screenshot_with_puppeteer/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/take_screenshot_with_puppeteer/Program.cs) |
| Export and import profiles to/from .kameleo files on disk | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/profile_export_import/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/profile_export_import/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/profile_export_import/Program.cs) |
| Launch a profile with CLI args, Selenium options, or prefs | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/start_browser_with_additional_options/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/start_browser_with_additional_options/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/start_browser_with_additional_options/Program.cs) |
| Upgrade a profile's browser kernel to the latest version | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/upgrade_profile/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/upgrade_profile/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/upgrade_profile/Program.cs) |
| Upload a file to a website using Selenium | — | — | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/file_upload_with_selenium/Program.cs) |
| Automate an iOS/Safari mobile profile with Selenium on desktop | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/automate_mobile_profiles_on_desktop/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/automate_mobile_profiles_on_desktop/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/automate_mobile_profiles_on_desktop/Program.cs) |
| Intercept and redirect network traffic using Selenium | — | — | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/modify_request_response_with_selenium/Program.cs) |
| Use the Kameleo API with CommonJS instead of ESM modules | — | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/commonjs/index.js) | — |
| Intercept, redirect, and replace responses with Playwright | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/modify_network_request_response_with_playwright/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/modify_network_request_response_with_playwright/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/modify_network_request_response_with_playwright/Program.cs) |
| Use init scripts, evaluate, screenshots, and video recording | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/python/examples/playwright_advanced_features/app.py) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/typescript/examples/playwright_advanced_features/index.js) | [View](https://github.com/kameleo-io/kameleo/blob/master/sdk/csharp/examples/playwright_advanced_features/Program.cs) |
⌘K
---
# Architecture overview | Kameleo Developer Center
Architecture overview
Copy
=================================
Kameleo is composed of cooperating components running both locally (on your machine) and in the cloud. Understanding their responsibilities helps when automating flows, diagnosing issues, or scaling usage across teams.
High-level diagram
------------------
Junglefox instance
Profile #2 data
Chroma instance
Profile #1 data
GUI
Your automation scripts
Kameleo Cloud Services
Local Engine instance
Core components
---------------
**Kameleo Engine (local)**
The central orchestrator that runs on your computer. It exposes a local REST API (default: `http://localhost:5050`) used by the Desktop GUI, your automation scripts (SDKs / HTTP calls), and other tools. All functional operations you perform - creating profiles, launching browsers, exporting cookies, shutting down sessions - are executed by this process.
**GUI (Desktop UI)**
Primarily a rich client atop the local API, but with added convenience and productivity features.
**Automation scripts (SDKs & custom code)**
Your scripts (C#, TypeScript/JavaScript, Python, etc.) talk directly to the local API or via official SDKs. They perform the same actions the GUI does, enabling CI/CD and large‑scale orchestration.
**Cloud services**
Kameleo cloud-side infrastructure provides authentication, subscription & team management, fingerprint generation, and other remote capabilities the Engine depends on. The Engine maintains secure sessions with these services as needed.
**Profile data (virtual browsers)**
Each running browser instance (e.g., Chroma, Junglefox) is tied to a virtual browser profile storing fingerprint parameters, storage (cookies, localStorage), stateful artifacts, and session history. The Engine persists and updates these as you operate the profile.
[On this page](https://developer.kameleo.io/reference/architecture-overview/)
* [High-level diagram](https://developer.kameleo.io/reference/architecture-overview/#high-level-diagram)
* [Core components](https://developer.kameleo.io/reference/architecture-overview/#core-components)
⌘K
---
# Configuration options | Kameleo Developer Center
Configuration options
Copy
=================================
This page lists every supported configuration key for the Kameleo Engine service. For procedural guidance (where to place `appsettings.json`, how to set environment variables or flags, and precedence rules) see [Configure](https://developer.kameleo.io/getting-started/configure/)
.
All keys are optional unless stated. Defaults apply when omitted. Precedence (highest to lowest): flags > environment variables > file.
Configuration keys
------------------
| JSON key | Environment variable | Command line flag | Default | Description |
| --- | --- | --- | --- | --- |
| `ListeningHost` | `LISTENINGHOST` | `listeningHost` | `+` | Host interface to bind. `+` accepts connections from any network interface. |
| `ListeningPort` | `LISTENINGPORT` | `listeningPort` | `5050` | TCP port exposed for the local API. |
| `Pat` | `PAT` | `pat` | (none) | Personal access token for authentication. Generate one at [https://login.kameleo.io/PAT](https://login.kameleo.io/PAT)
. |
| `Verbose` | `VERBOSE` | `verbose` | `1` | Log verbosity: `0` = minimal, `1` = normal, `2` = detailed diagnostics. |
| `UserDirectoryOverride` | `USERDIRECTORYOVERRIDE` | `userDirectoryOverride` | (platform default) | Overrides default user directory (`%APPDATA%\Kameleo` or `~/Library/Application Support/Kameleo`). |
| `WorkspaceFolder` | `WORKSPACEFOLDER` | `workspaceFolder` | `Workspace` | Workspace root folder. Relative paths resolve under the user directory. |
Notes
-----
* Omitted authentication key (`Pat`) starts the service accountless; some features will be unavailable.
* Use higher verbosity (`Verbose=2`) only for troubleshooting; it increases log volume.
* Paths can be absolute or relative. Relative paths resolve against the effective user directory (override if set).
[On this page](https://developer.kameleo.io/reference/configuration-options/)
* [Configuration keys](https://developer.kameleo.io/reference/configuration-options/#configuration-keys)
* [Notes](https://developer.kameleo.io/reference/configuration-options/#notes)
⌘K
---
# API error handling | Kameleo Developer Center
API error handling
Copy
==============================
Every non-2xx response from the Local API is an error. All SDKs deserialize the response body into a structured `ProblemResponse` object and surface it through a typed exception so you can react programmatically.
ProblemResponse structure
-------------------------
The API always returns an [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457)
`ProblemResponse` body on errors.
| Field | Type | Description |
| --- | --- | --- |
| `status` | `integer` | The HTTP status code (e.g., `404`, `422`). |
| `errorCode` | `ErrorCode` | A machine-readable error code. Use this for programmatic branching. |
| `type` | `string` | A URI identifying the problem type. |
| `title` | `string` | A short, human-readable summary of the problem. |
| `detail` | `string` | A human-readable explanation of this specific occurrence. |
| `instance` | `string` | A URI identifying the specific occurrence. |
| `errors` | `object` | Validation errors keyed by field name. |
##### Note
Always branch on `errorCode`, not on `title` or `detail`. The human-readable fields are intended for logging and debugging, and their exact wording may change between versions.
ErrorCode values
----------------
The `errorCode` field is a string enum. All possible values are listed below.
| Value | Description |
| --- | --- |
| `no_token` | No authentication token was provided. |
| `unauthorized` | The current access level is not authorized for this operation. |
| `invalid_session` | The session is invalid. |
| `token_expired` | The authentication token has expired. |
| `authentication_failed` | Authentication against Kameleo cloud services failed. |
| `accountless_limit_reached` | The accountless usage limit is reached. |
| `no_capability` | The subscription does not include the required capability. |
| `no_cookies_capability` | The subscription does not include the cookie management capability. |
| `no_mobile_capability` | The subscription does not include mobile profiles. |
| `no_proxy_test_capability` | The subscription does not include proxy testing. |
| `no_cloud_capability` | The subscription does not include cloud profiles. |
| `no_local_capability` | The subscription does not include local profiles. |
| `no_groups_capability` | The subscription does not include team groups. |
| `no_headless_capability` | The subscription does not include headless browser support. |
| `profile_not_found` | No profile with the given ID exists. |
| `profile_already_running` | The profile is already running; start was called again. |
| `profile_not_running` | The profile is not running; an operation requiring a running profile was called. |
| `profile_running` | The profile is currently running; the operation requires it to be stopped. |
| `profile_locked` | The profile is locked by another process. |
| `profile_syncing` | The profile is currently syncing with cloud. |
| `profile_never_started` | The profile has never been started; no browser data exists yet. |
| `browser_engine_outdated` | The local browser kernel is outdated and must be updated. |
| `proxy_connection_issue` | Failed to connect to the configured proxy. |
| `cloud_limit_reached` | The cloud profile storage limit is reached. |
| `cloud_profile_not_exportable` | Cloud profiles cannot be exported. |
| `profile_already_imported` | The profile has already been imported. |
| `incompatible_file` | The file is incompatible with this version of Kameleo. |
| `running_profiles_limit_reached` | Concurrent browser limit is reached. |
| `running_mobile_profiles_limit_reached` | Mobile concurrent browser limit is reached. |
| `profile_minutes_limit_reached` | The browser usage quota is exhausted. |
| `downloaded_cloud_profile_bytes_limit_reached` | The cloud profile download quota is exhausted. |
| `folder_not_found` | No folder with the given ID exists. |
| `database_not_found` | The local database could not be found. |
| `validation_failed` | Request body validation failed; see the `errors` field for details. |
| `invalid_request` | The request is malformed or contains invalid parameters. |
| `service_not_ready` | The Engine is still starting up and cannot handle requests yet. |
| `rate_limit_exceeded` | Too many requests were sent in a short period. |
| `kernel_download_limit_reached` | The browser kernel download quota is exhausted. |
| `kernel_not_found` | No kernel matching the requested criteria could be found. |
| `kernel_in_use` | The kernel is in use and cannot be removed. |
| `cdp_connection_failed` | The Chrome DevTools Protocol connection to the browser failed. |
| `browser_instrumentation_disabled` | Browser instrumentation is disabled for this profile. |
| `vnc_not_supported` | VNC is not supported on this platform or configuration. |
| `upload_failed` | Uploading the file failed. |
| `unexpected_error` | An unexpected internal error occurred. |
##### Note
For how concurrent browser (CB) and mobile CB quotas work and how to check current usage, see [Usage limits](https://developer.kameleo.io/reference/usage-limits/)
.
Exception types per SDK
-----------------------
### Python — `ApiException`
Raised by every API call that returns a non-2xx status. Import it from `kameleo.local_api_client.exceptions`.
| Property | Type | Description |
| --- | --- | --- |
| `status` | `int` | HTTP status code. |
| `error_code` | `ErrorCode \| str \| None` | Deserialized `ErrorCode` enum value, or the raw string if unknown. |
| `problem` | `ProblemResponse \| None` | Full deserialized `ProblemResponse`. |
| `reason` | `str` | HTTP reason phrase. |
| `body` | `str \| None` | Raw response body string. |
| `headers` | any | Response headers. |
### JavaScript / TypeScript — `ResponseError`
Thrown by every SDK method on a non-2xx response. Import it from `@kameleo/local-api-client`.
| Property | Type | Description |
| --- | --- | --- |
| `response` | `Response` | The raw `fetch` `Response` object. |
| `errorCode` | `ErrorCode \| undefined` | Deserialized `ErrorCode` enum value. |
| `problem` | `ProblemResponse \| undefined` | Full deserialized `ProblemResponse`. |
| `message` | `string` | Human-readable error message. |
### C# — `ApiException`
Thrown by every async API method on a non-2xx response. Located in `Kameleo.LocalApiClient.Client`.
| Property | Type | Description |
| --- | --- | --- |
| `StatusCode` | `int` | HTTP status code. |
| `ErrorCode` | `ErrorCode?` | Deserialized `ErrorCode` enum value (shortcut to `Problem.ErrorCode`). |
| `Problem` | `ProblemResponse` | Full deserialized `ProblemResponse`. |
| `Message` | `string` | Human-readable error message (inherited from `Exception`). |
| `Headers` | `Multimap` | Response headers. |
Catching and handling errors
----------------------------
The following examples show the recommended pattern: catch the SDK exception, check `errorCode` for known conditions, and let unexpected errors propagate or be handled at a higher level.
[Python](https://developer.kameleo.io/reference/api-error-handling/#python)
[JavaScript](https://developer.kameleo.io/reference/api-error-handling/#javascript)
[C#](https://developer.kameleo.io/reference/api-error-handling/#c)
`from kameleo.local_api_client.exceptions import ApiException from kameleo.local_api_client.models import ErrorCode try: client.profile.delete_profile(profile_id) except ApiException as ex: if ex.error_code == ErrorCode.PROFILE_NOT_FOUND: # Ignore: already deleted print(f"Already deleted: {ex}") else: print(f"Unexpected error: {ex}") raise`
[On this page](https://developer.kameleo.io/reference/api-error-handling/)
* [ProblemResponse structure](https://developer.kameleo.io/reference/api-error-handling/#problemresponse-structure)
* [ErrorCode values](https://developer.kameleo.io/reference/api-error-handling/#errorcode-values)
* [Exception types per SDK](https://developer.kameleo.io/reference/api-error-handling/#exception-types-per-sdk)
* [Python — ApiException](https://developer.kameleo.io/reference/api-error-handling/#python--apiexception)
* [JavaScript / TypeScript — ResponseError](https://developer.kameleo.io/reference/api-error-handling/#javascript--typescript--responseerror)
* [C# — ApiException](https://developer.kameleo.io/reference/api-error-handling/#c--apiexception)
* [Catching and handling errors](https://developer.kameleo.io/reference/api-error-handling/#catching-and-handling-errors)
⌘K
---
# Blacklisted browser switches | Kameleo Developer Center
Blacklisted browser switches
Copy
========================================
Kameleo blocks specific native browser command-line switches to preserve coordinated fingerprint integrity, maintain isolation of managed profile data, and avoid conflicts with internal orchestration. Passing any listed switch results in an error and the profile will not start.
Chroma (Chromium-based)
-----------------------
| Switch | Rationale |
| --- | --- |
| `--incognito` | Incognito mode discards persistent data Kameleo relies on |
| `--remote-debugging-port` | Port is managed internally |
| `--user-data-dir` | Profile directory is managed & isolated by Kameleo |
| `--proxy-server` | Proxy is configured via profile settings and validated |
| `--disable-3d-apis` | Used conditionally when WebGL blocking is enabled; manual override may desync masking state |
Junglefox (Firefox-based)
-------------------------
| Switch | Rationale |
| --- | --- |
| `-private` / `--private` / `-private-window` | Incognito mode discards persistent data Kameleo relies on |
| `--profile` | Profile directory is managed & isolated by Kameleo |
| `--marionette` | Port is managed internally |
| `-juggler` / `--juggler` | Connection is managed internally |
Notes
-----
* This list may expand over time; newly blocked switches will raise the same validation error.
* Use profile properties (e.g., proxy configuration, start page) instead of forcing low‑level flags.
* For additional, general browser command-line options, see the external references below.
External references
-------------------
* Chromium switches: [https://peter.sh/experiments/chromium-command-line-switches/](https://peter.sh/experiments/chromium-command-line-switches/)
* Firefox switches: [https://wiki.mozilla.org/Firefox/CommandLineOptions](https://wiki.mozilla.org/Firefox/CommandLineOptions)
[On this page](https://developer.kameleo.io/reference/blacklisted-browser-switches/)
* [Chroma (Chromium-based)](https://developer.kameleo.io/reference/blacklisted-browser-switches/#chroma-chromium-based)
* [Junglefox (Firefox-based)](https://developer.kameleo.io/reference/blacklisted-browser-switches/#junglefox-firefox-based)
* [Notes](https://developer.kameleo.io/reference/blacklisted-browser-switches/#notes)
* [External references](https://developer.kameleo.io/reference/blacklisted-browser-switches/#external-references)
⌘K
---
# Engine exit codes | Kameleo Developer Center
Engine exit codes
Copy
=============================
Kameleo Engine returns specific numeric exit codes to signal termination reasons for automation scripts, CI pipelines, and monitoring agents. Codes are stable; new codes may be added over time. A value of `0` always indicates success (standard convention) and is omitted below.
Exit codes
----------
| Code | Name (mnemonic) | Meaning | Typical remediation |
| --- | --- | --- | --- |
| 100 | AUTH\_LOGIN\_ERROR | Login error (temporary service or credential issue) | Retry after short delay; verify credentials and service status. |
| 101 | SUBSCRIPTION\_INACTIVE | Subscription inactive or expired | Renew or reactivate subscription; verify billing status. |
| 102 | AUTH\_INVALID\_CREDENTIALS | Invalid or expired credentials | Reauthenticate the app. |
| 103 | THROTTLE\_LIMIT | Request throttle limit reached | Back off (exponential); reduce parallel requests. |
| 104 | TEAM\_SUBSCRIPTION\_INACTIVE | Team subscription inactive | Team owner must reactivate; check team billing. |
| 105 | CONCURRENT\_SESSION\_LIMIT | Concurrent session limit reached | Close/stop other sessions or upgrade plan. |
| 106 | TEAM\_USER\_LIMIT | Team user limit exceeded | Remove unused members or upgrade plan. |
| 107 | FREE\_TIER\_ABUSE | Free tier abuse detected | Contact support if false positive; otherwise comply with terms. |
| 108 | VERSION\_NOT\_SUPPORTED | Version can't be used anymore | Upgrade to latest version to continue using the application. |
| 109 | DOCKER\_NOT\_ALLOWED | Subscription is missing Docker capability | Upgrade to a plan that includes Docker support. |
| 110 | REFRESH\_TOKEN\_EXPIRED | Refresh token has expired | Log in again to obtain a new refresh token. |
| 111 | PAT\_INVALID | Personal access token is invalid | Generate a new personal access token at [https://login.kameleo.io/PAT](https://login.kameleo.io/PAT)
. |
| 112 | DEVICE\_ACCOUNTLESS\_LIMIT | Device has been used with a registered account | Use the registered account or contact support. |
| 113 | UNSUPPORTED\_AUTH\_METHOD | The email+password authentication is not supported | Use PAT instead, see: [Configure](https://developer.kameleo.io/getting-started/configure/) |
| 114 | AUTH\_PARAMS\_EXPIRED | Expired authentication parameters | Retry authentication. |
| 200 | INTERNAL\_UNKNOWN | Unknown internal error | Re-run with `Verbose=2`; file ticket with logs. |
| 201 | NETWORK\_FAILURE | Network connection failed | Check connectivity, proxy/firewall rules; retry. |
| 202 | INSTANCE\_ALREADY\_RUNNING | Another instance already running | Stop existing instance or use different port/user directory. |
[On this page](https://developer.kameleo.io/reference/engine-exit-codes/)
* [Exit codes](https://developer.kameleo.io/reference/engine-exit-codes/#exit-codes)
⌘K
---
# Performance benchmark | Kameleo Developer Center
Performance benchmark
Copy
=================================
This benchmark helps you estimate the expected performance of Kameleo-based scraping setups and choose the most suitable server type for your workload. By comparing throughput and cost efficiency across different EC2 instances, you can make data-driven decisions about scaling, concurrency tuning and infrastructure budgeting.
Scope
-----
Compares `m7i.large`, `m7i.xlarge`, and `m7i.2xlarge` instance types using two workloads (Wikipedia archival pages and Amazon product detail pages). Each workload: (1) discover target URLs from a seed page; (2) fetch each page sequentially and persist to disk. Metrics exclude seed pages.
Test environment
----------------
All instances: Intel Xeon Platinum 8488C, DDR5 memory, Chroma browser build 141.
### Instance specifications
| Instance | vCPU | RAM (GiB) | Hourly price (USD) |
| --- | --- | --- | --- |
| m7i.large | 2 | 8 | 0.21275 |
| m7i.xlarge | 4 | 16 | 0.4255 |
| m7i.2xlarge | 8 | 32 | 0.851 |
### Concurrency levels
Profile counts tested: 2, 5, 10, 15, 20, 25, 30, 35, 40. All profiles were instrumented by the same script but each profile acted as an independent sequential scraper, there was no inter‑profile communication.
Workloads
---------
### Wikipedia archival pages
Seed index enumerates yearly subpages. Measurement starts at initial navigation (including enumeration) and ends when the final subpage is saved. Only subpages count toward throughput.
### Amazon product detail pages
Listing page yields product detail URLs. Each product page is fetched and saved sequentially. Only successful product detail pages count toward throughput.
Results
-------
Graphs (time vs workers and cost vs workers) are provided for both workloads and all instance sizes.
### Throughput (time)
#### Wikipedia throughput
Low concurrency (2 running profiles) shows minimal difference between instance sizes (resource underutilization). Throughput improves with additional profiles until saturation; m7i.2xlarge sustains higher mid‑range concurrency before slowdown. Beyond optimal profile count latency increases and error rate rises (e.g., timeouts) decreasing effective throughput.

Wikipedia scraping speed
#### Amazon throughput
Similar early scaling. Benefits of larger instances appear sooner due to heavier pages. Throughput declines at lower worker counts than Wikipedia because dynamic content increases CPU and memory pressure.

Amazon scraping speed
### Cost efficiency
Cost per useful page depends on both hourly instance price and completion time.
#### Wikipedia cost
Underutilization at low profile counts favors smaller instances. Excessive concurrency on smaller instances degrades performance enough that their cost per page exceeds larger instances. Around ~10 running profiles cost efficiency converges across sizes.

Wikipedia scraping cost per 1000 pages
#### Amazon cost
Heavier workload increases contention; smaller instances show sharper cost per page increase as profile count grows. Largest instance maintains more stable efficiency at higher concurrency.

Amazon scraping cost per 1000 pages
Key takeaways
-------------
| Instance | Effective concurrency band | Notes |
| --- | --- | --- |
| m7i.large | 2–5 profiles | Early CPU saturation; suitable for light loads. |
| m7i.xlarge | 5–10 profiles | Handles medium concurrency without disproportionate cost. |
| m7i.2xlarge | ≥15 profiles | Maintains throughput where smaller sizes degrade. |
General: Larger instances defer saturation enabling more concurrent browsers before resource contention reduces throughput.
Interpretation notes
--------------------
* Results reflect sequential page processing per running profile; different orchestration (e.g., parallel fetch within profiles) would change scaling characteristics.
* Network variability, target site rate limits, and transient page dynamics can introduce run‑to‑run variance; reported behavior is representative not absolute.
* Optimal profile count should balance throughput with error rate; exceeding saturation increases timeouts and reduces effective pages saved.
[On this page](https://developer.kameleo.io/reference/performance-benchmark/)
* [Scope](https://developer.kameleo.io/reference/performance-benchmark/#scope)
* [Test environment](https://developer.kameleo.io/reference/performance-benchmark/#test-environment)
* [Instance specifications](https://developer.kameleo.io/reference/performance-benchmark/#instance-specifications)
* [Concurrency levels](https://developer.kameleo.io/reference/performance-benchmark/#concurrency-levels)
* [Workloads](https://developer.kameleo.io/reference/performance-benchmark/#workloads)
* [Wikipedia archival pages](https://developer.kameleo.io/reference/performance-benchmark/#wikipedia-archival-pages)
* [Amazon product detail pages](https://developer.kameleo.io/reference/performance-benchmark/#amazon-product-detail-pages)
* [Results](https://developer.kameleo.io/reference/performance-benchmark/#results)
* [Throughput (time)](https://developer.kameleo.io/reference/performance-benchmark/#throughput-time)
* [Wikipedia throughput](https://developer.kameleo.io/reference/performance-benchmark/#wikipedia-throughput)
* [Amazon throughput](https://developer.kameleo.io/reference/performance-benchmark/#amazon-throughput)
* [Cost efficiency](https://developer.kameleo.io/reference/performance-benchmark/#cost-efficiency)
* [Wikipedia cost](https://developer.kameleo.io/reference/performance-benchmark/#wikipedia-cost)
* [Amazon cost](https://developer.kameleo.io/reference/performance-benchmark/#amazon-cost)
* [Key takeaways](https://developer.kameleo.io/reference/performance-benchmark/#key-takeaways)
* [Interpretation notes](https://developer.kameleo.io/reference/performance-benchmark/#interpretation-notes)
⌘K
---
# API reference | Kameleo Developer Center
API reference
Copy
=========================
All endpoints below are available through the official Kameleo SDKs. Prefer using an SDK for typed models, auth handling, and forward compatibility instead of crafting raw HTTP requests manually.
OpenAPI v3 specification: [swagger.json](https://developer.kameleo.io/static/swagger.json)
Official SDK packages:
* Python: [kameleo-local-api-client (PyPI)](https://pypi.org/project/kameleo-local-api-client/)
* JavaScript / TypeScript: [@kameleo/local-api-client (npm)](https://www.npmjs.com/package/@kameleo/local-api-client)
* C#: [Kameleo.LocalApiClient (NuGet)](https://www.nuget.org/packages/Kameleo.LocalApiClient)
⌘K
---
# Using Fingerprint Inspector | Kameleo Developer Center
Using Fingerprint Inspector
Copy
=======================================
Fingerprint Inspector helps you reverse engineer how a site fingerprints a profile's browser, by showing you which APIs it calls - for example reading canvas or WebGL output, audio data, or navigator properties. It works by capturing these calls inside the profile's browser and streaming them to a dedicated panel in DevTools, so you can validate that your masking setup behaves as expected or debug why a site treats a profile as suspicious. In this tutorial, you'll enable Fingerprint Inspector on a profile and read its live events in DevTools.
Prerequisites
-------------
* Completion of the [Quickstart](https://developer.kameleo.io/getting-started/quickstart/)
guide
* The Kameleo app running locally
* An existing Chroma profile (Junglefox profiles aren't supported yet)
1\. Start a profile with Fingerprint Inspector enabled
------------------------------------------------------
Open the dashboard and locate the profile you want to inspect. Click its **three-dot** menu, then select **Fingerprint Inspector**.
The profile starts as usual, and its browser window opens with fingerprint inspection turned on.
2\. Open the Fingerprint Inspector panel
----------------------------------------
The first time you start a profile this way, a short guide opens in a new tab explaining how to open DevTools. Follow it, or use these steps directly:
1. Open DevTools (`F12`, or `Ctrl+Shift+I` on Windows/Linux, `Cmd+Option+I` on macOS).
2. Select the **Fingerprint Inspector** tab. If you don't see it, click the **»** overflow arrow at the right end of the tab bar to reveal hidden panels.
The panel opens empty, ready to display events as the profile's browser makes fingerprinting-related calls.
3\. Browse and read the results
-------------------------------
Navigate to any website in the profile's browser window. As the page runs scripts that call fingerprinting-related APIs, matching rows appear in the panel in real time, each showing the timestamp, the API name, its parameters, and its return value.
Use the search box to filter events by name, category, or value, and click **Clear** to reset the list.
##### Results are shared across tabs
The panel isn't scoped to the tab it was opened from. It shows fingerprinting calls from every open tab in the profile's browser, so it doesn't matter which tab you're on when you check it.
Events are tagged with a category so you can quickly tell which technique a site used, such as:
* Canvas and WebGL/WebGPU rendering output
* Audio processing
* Navigator properties (hardware, locale, user agent, and similar)
* Media devices, WebRTC, geolocation, Bluetooth, and speech voices
[On this page](https://developer.kameleo.io/tutorials/using-fingerprint-inspector/)
* [Prerequisites](https://developer.kameleo.io/tutorials/using-fingerprint-inspector/#prerequisites)
* [1\. Start a profile with Fingerprint Inspector enabled](https://developer.kameleo.io/tutorials/using-fingerprint-inspector/#1-start-a-profile-with-fingerprint-inspector-enabled)
* [2\. Open the Fingerprint Inspector panel](https://developer.kameleo.io/tutorials/using-fingerprint-inspector/#2-open-the-fingerprint-inspector-panel)
* [3\. Browse and read the results](https://developer.kameleo.io/tutorials/using-fingerprint-inspector/#3-browse-and-read-the-results)
⌘K
---
# Unknown
```json
{
"openapi": "3.0.4",
"info": {
"title": "kameleo-local-api",
"description": "You can use the following API endpoints to communicate with the local running Kameleo programmatically.",
"termsOfService": "https://kameleo.io",
"contact": {
"name": "Kameleo Team",
"url": "https://developer.kameleo.io"
},
"version": "5.2.0"
},
"servers": [
{
"url": "http://localhost:5050"
}
],
"paths": {
"/profiles/{guid}/cookies": {
"get": {
"tags": ["Cookie"],
"summary": "Retrieves the list of cookies stored in the profile's browser. Note that this list does not include session cookies, which are not\r\npersisted between browser launches.",
"operationId": "ListCookies",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BrowserCookie"
}
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile must be terminated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"post": {
"tags": ["Cookie"],
"summary": "Adds a list of cookies to the profile, allowing you to inject cookies before starting the profile. If cookies already exist for a domain,\r\nthey will be replaced with the new ones.",
"operationId": "AddCookies",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CookieRequest"
}
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/BrowserCookie"
}
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile must be terminated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"delete": {
"tags": ["Cookie"],
"summary": "Deletes all the cookies stored in the profile, which will likely log the profile out of all websites.",
"operationId": "DeleteCookies",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK."
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile must be terminated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/fingerprints": {
"get": {
"tags": ["Fingerprint"],
"summary": "Retrieves a set of 25 fingerprints based on specified criteria, with the most recent browser versions at the beginning of the list. Note\r\nthat calling this method multiple times will return different sets of fingerprints.",
"operationId": "SearchFingerprints",
"parameters": [
{
"name": "deviceType",
"in": "query",
"description": "Filter option for the Device Type. Possible values are 'desktop', 'mobile'.\r\nDefaults to desktop, unless overridden by other parameters.",
"schema": {
"type": "string",
"example": "desktop"
},
"example": "desktop"
},
{
"name": "osFamily",
"in": "query",
"description": "Filter option for os family. Possible values are 'windows', 'macos', 'linux', 'android', 'ios'.\r\nDefaults to the Engine's OS, unless overridden by other parameters.",
"schema": {
"type": "string",
"example": "windows"
},
"example": "windows"
},
{
"name": "browserProduct",
"in": "query",
"description": "Filter option for browser product. Possible values are 'chrome', 'firefox', 'edge', 'safari'.\r\nDefaults to Chrome, unless overridden by other parameters.",
"schema": {
"type": "string",
"example": "safari"
},
"example": "safari"
},
{
"name": "browserVersion",
"in": "query",
"description": "Filter option for the browser version.\r\nIncludes an optional sign (<, >=, etc.) and a major version number (e.g. 145)",
"schema": {
"type": "string",
"example": "145"
},
"example": "145"
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FingerprintPreview"
}
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"402": {
"description": "Payment Required",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders": {
"get": {
"tags": ["Folder"],
"summary": "Retrieve the complete list of folders in your workspace. Use this endpoint to see the entire folder hierarchy - including subfolders and\r\nunassigned profiles.",
"operationId": "ListFolders",
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ListFoldersResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/{guid}": {
"get": {
"tags": ["Folder"],
"summary": "Fetch detailed information for a specific folder by its unique GUID. Use this to review the folder’s metadata, contained profiles, and\r\nsharing settings.",
"operationId": "ReadFolder",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the folder.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderResponse"
}
}
}
},
"404": {
"description": "Folder is not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"put": {
"tags": ["Folder"],
"summary": "Updates the details of an existing folder, not including its content.",
"operationId": "UpdateFolder",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the folder.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/UpdateFolderRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderResponse"
}
}
}
},
"404": {
"description": "Folder is not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"400": {
"description": "The provided data failed validation.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"delete": {
"tags": ["Folder"],
"summary": "Deletes a folder along with all its subfolders. Profiles within the folder will either be deleted or moved to the top-level based on the\r\nquery parameters.",
"operationId": "DeleteFolder",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the folder.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "includeProfiles",
"in": "query",
"description": "Flag to indicate if the contained profiles should be deleted (true) or moved to the top-level (false).",
"schema": {
"type": "boolean",
"default": false
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeleteFolderResponse"
}
}
}
},
"404": {
"description": "Folder is not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/new": {
"post": {
"tags": ["Folder"],
"summary": "Create a new folder in your workspace by providing a human-readable name in the request body. Use this to organize your profiles\r\neffectively.",
"operationId": "CreateFolder",
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/CreateFolderRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderResponse"
}
}
}
},
"400": {
"description": "The provided data failed validation.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/{guid}/add": {
"post": {
"tags": ["Folder"],
"summary": "Adds the given profile to the specified folder.",
"operationId": "AddProfileToFolder",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the folder.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/AddProfileToFolderRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/{guid}/{profileId}": {
"delete": {
"tags": ["Folder"],
"summary": "Removes the given profile from the specified folder.",
"operationId": "RemoveProfileFromFolder",
"parameters": [
{
"name": "guid",
"in": "path",
"description": "The unique identifier of the folder.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/share": {
"get": {
"tags": ["Folder"],
"summary": "Retrieve the sharing options available for folders. Use this endpoint to review the list of users and roles that can access your folder\r\nresources.",
"operationId": "ReadSharingOptions",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SharingOptionsResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/folders/{guid}/share": {
"post": {
"tags": ["Folder"],
"summary": "Update the sharing settings for a folder by submitting a list of share access rules (user and role details) in the request body. Use this\r\nto adjust access permissions as needed.",
"operationId": "ShareGroup",
"parameters": [
{
"name": "guid",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/ShareGroupRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FolderResponse"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/general/healthcheck": {
"get": {
"tags": ["General"],
"summary": "Health check request to test if Kameleo has been started and accepting connections.",
"operationId": "Healthcheck",
"responses": {
"200": {
"description": "OK."
},
"503": {
"description": "Service Unavailable.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/general/user-info": {
"get": {
"tags": ["General"],
"summary": "Fetch detailed information about your user account.",
"operationId": "GetUserInfo",
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserInfoResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/general/terminate": {
"post": {
"tags": ["General"],
"summary": "Terminate your current Kameleo session by deauthenticating and exiting the Engine. Use this to safely close your session and release any\r\nassociated resources.",
"operationId": "TerminateApplication",
"responses": {
"200": {
"description": "OK."
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/general/test-proxy": {
"post": {
"tags": ["General"],
"summary": "Tests the given proxy connection and returns every individual test step together with an overall summary. The summary is 'success' when\r\nevery step passes, 'partial_success' when the website could be reached through at least one of IPv4, IPv6 or DNS name and the IP location\r\nlookup also succeeded, otherwise 'failure'.",
"operationId": "TestProxy",
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/TestProxyRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestProxyResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"503": {
"description": "The proxy connection failed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/kernels": {
"get": {
"tags": ["Kernel"],
"summary": "Gets the list of all the available kernels.",
"operationId": "ListKernels",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/KernelResponse"
}
}
}
}
}
}
}
},
"/kernels/{id}/install": {
"post": {
"tags": ["Kernel"],
"summary": "Installs a kernel to the local file system.",
"operationId": "InstallKernel",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Unique identifier of the kernel.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KernelResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"404": {
"description": "The kernel is not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"429": {
"description": "Too Many Requests",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
}
},
"/kernels/{id}/remove": {
"post": {
"tags": ["Kernel"],
"summary": "Removes a kernel from the local file system.",
"operationId": "RemoveKernel",
"parameters": [
{
"name": "id",
"in": "path",
"description": "Unique identifier of the kernel.",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KernelResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"404": {
"description": "The kernel is not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"409": {
"description": "The kernel can't be removed because it is currently in use, but it was marked for deletion",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KernelResponse"
}
}
}
}
}
}
},
"/profiles": {
"get": {
"tags": ["Profile"],
"summary": "Retrieve a list of all profiles loaded in your workspace. Use this endpoint to view a preview of each profile so you can quickly assess\r\navailable profiles.",
"operationId": "ListProfiles",
"parameters": [
{
"name": "lifetimeState",
"in": "query",
"description": "The lifetime state of the profiles to return (optional)",
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileLifetimeState"
}
]
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProfilePreview"
}
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/new": {
"post": {
"tags": ["Profile"],
"summary": "Create a new profile based on a selected fingerprint. Supply the required configuration in the request body, then receive the newly\r\ncreated profile’s full details.",
"operationId": "CreateProfile",
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/CreateProfileRequest"
}
]
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Fingerprint not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}": {
"put": {
"tags": ["Profile"],
"summary": "Update an existing profile’s settings by providing the new configuration options in the request body. Use this to modify aspects like\r\nspoofing options or proxy settings, then receive the updated profile details.",
"operationId": "UpdateProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/UpdateProfileRequest"
}
]
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Cannot edit profile because it is running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"get": {
"tags": ["Profile"],
"summary": "Gets the profile with the specified GUID from the current workspace. On startup, Kameleo will automatically scan and load profiles stored\r\nin your workspace folder on startup.",
"operationId": "ReadProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
},
"delete": {
"tags": ["Profile"],
"summary": "Permanently delete a profile from your workspace.",
"operationId": "DeleteProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK."
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile is running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/test-proxy": {
"post": {
"tags": ["Profile"],
"summary": "Tests the proxy connection configured on the given profile and returns every individual test step together with an overall summary. The\r\nsummary is 'success' when every step passes, 'partial_success' when the website could be reached through at least one of IPv4, IPv6 or DNS\r\nname and the IP location lookup also succeeded, otherwise 'failure'.",
"operationId": "TestProfileProxy",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TestProxyResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"503": {
"description": "The proxy connection failed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/status": {
"get": {
"tags": ["Profile"],
"summary": "Check the current status of a profile, including its lifecycle and persistence states.",
"operationId": "GetProfileStatus",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StatusResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/start": {
"post": {
"tags": ["Profile"],
"summary": "Starts the selected profile by transitioning its status to 'starting', launching the kernel (Chroma or Junglefox) associated with the\r\nprofile, and then changing its status to 'running'.\r\nIf there is an error during start-up, it will be 'terminated'. Note that the required kernel might not be available locally, so it may be\r\ndownloaded during the profile start.\r\nOptional command line arguments or settings can be passed to the browser engines.",
"operationId": "StartProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/BrowserSettings"
}
],
"description": "Extra settings and preferences that can be applied to the browser at startup."
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StatusResponse"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"402": {
"description": "Payment Required",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile already running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"429": {
"description": "Too Many Requests",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"503": {
"description": "Service Unavailable",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/stop": {
"post": {
"tags": ["Profile"],
"summary": "Stop a running profile by gracefully shutting down its browser engine and releasing allocated resources. Use this endpoint to transition\r\nthe profile from 'running' to 'terminated' state.",
"operationId": "StopProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StatusResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Profile is not running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/export": {
"post": {
"tags": ["Profile"],
"summary": "Export a profile to a .kameleo file by providing the target file path in the request body. Use this to back up all profile attributes —\r\nincluding settings, browsing data, cookies, history, bookmarks, and extensions — for later restoration or migration.",
"operationId": "ExportProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/ExportProfileRequest"
}
],
"description": "Defines the target location for profile export."
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Cannot export profile if currently running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/duplicate": {
"post": {
"tags": ["Profile"],
"summary": "Duplicate an existing profile by creating an exact copy with a new unique identifier. Use this endpoint to clone a profile while preserving\r\nall its configuration details and data.",
"operationId": "DuplicateProfile",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"409": {
"description": "Cannot save profile because currently running.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/import": {
"post": {
"tags": ["Profile"],
"summary": "Imports a profile from a .kameleo file, effectively recreating the profile with all its attributes, including settings, browsing data,\r\ncookies, history, bookmarks, and any installed extensions/addons. If the profile is already loaded, the import process will fail.",
"operationId": "ImportProfile",
"requestBody": {
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/ImportProfileRequest"
}
],
"description": "Specifies the source location for profile import."
}
}
}
},
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
},
"/profiles/{profileId}/upgrade": {
"post": {
"tags": ["Profile"],
"summary": "Upgrades the profile's fingerprint to the most recent browser version available from the server.\r\nThis also updates the profile's corresponding kernel if there's a better match available for the new fingerprint.\r\nThe new fingerprint is tailored to the profile's current device, browser and operating system. Note that upgrading a profile's kernel will alter its browser fingerprint.",
"operationId": "UpgradeProfileKernel",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProfileResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"204": {
"description": "No new browser version is available for this profile."
},
"409": {
"description": "Cannot upgrade profile because it is running."
}
}
}
},
"/profiles/{profileId}/kernel-install": {
"post": {
"tags": ["Profile"],
"summary": "Installs the kernel that best suits the specified profile's fingerprint, downloading it if it's not already available locally.",
"operationId": "InstallProfileKernel",
"parameters": [
{
"name": "profileId",
"in": "path",
"description": "The unique identifier of the profile",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "OK.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/KernelResponse"
}
}
}
},
"404": {
"description": "Profile not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"429": {
"description": "Too Many Requests",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
},
"default": {
"description": "Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemResponse"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"AddProfileToFolderRequest": {
"required": ["profileId"],
"type": "object",
"properties": {
"profileId": {
"type": "string",
"description": "Unique identifier of the profile.",
"format": "uuid",
"example": "0036135c-6f62-429b-a9db-fd541aca96a7"
}
},
"additionalProperties": false
},
"AudioSpoofingType": {
"enum": ["off", "noise", "block"],
"type": "string",
"description": "Specifies how the audio will be spoofed. Possible values:\r\n'noise': Add some noise to the Audio generation\r\n'block': Completely block the Audio API\r\n'off': Turn off the spoofing, use the original settings"
},
"Browser": {
"required": ["major", "product", "version"],
"type": "object",
"properties": {
"product": {
"type": "string",
"description": "Product of the browser. Possible values are 'chrome', 'firefox', 'edge', 'safari'.",
"example": "chrome"
},
"major": {
"type": "integer",
"description": "Major version of the browser.",
"format": "int32",
"example": 81
},
"version": {
"type": "string",
"description": "Exact version of the browser.",
"example": "81.0.4044"
}
},
"additionalProperties": false
},
"BrowserCookie": {
"required": ["domain", "hostOnly", "httpOnly", "name", "path", "sameSite", "secure", "value"],
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "The domain attribute signifies the domain for which the cookie is valid and can be submitted with every request for this domain or its\r\nsubdomains. If this attribute is not specified, then the hostname of the originating server is used as the default value.",
"example": ".google.com"
},
"name": {
"type": "string",
"description": "The name for the Cookie.",
"example": "_ga"
},
"path": {
"type": "string",
"description": "The path attribute indicates a URL path that must exist in the requested URL in order to send the Cookie header. The %x2F (\"/\") character\r\nis considered a directory separator, and subdirectories match as well.",
"example": "/gmail/about"
},
"value": {
"type": "string",
"description": "The value of the Cookie.",
"example": "GA1.2-3.982544754.9825342343"
},
"hostOnly": {
"type": "boolean",
"description": "Host Only cookie means that the cookie should be handled by the browser to the server only to the same host/server that firstly sent it to\r\nthe browser.",
"example": false
},
"httpOnly": {
"type": "boolean",
"description": "When this attribute is set, client-side scripts are not allowed to access the cookie.",
"example": true
},
"secure": {
"type": "boolean",
"description": "A cookie with the Secure attribute is sent to the server only with an encrypted request over the HTTPS protocol, never with unsecured HTTP,\r\nand therefore can't easily be accessed by a man-in-the-middle attacker. Insecure sites (with http: in the URL) can't set cookies with the\r\nSecure attribute.",
"example": true
},
"sameSite": {
"type": "string",
"description": "The sameSite attribute lets servers require that a cookie shouldn't be sent with cross-origin requests (where Site is defined by the\r\nregistrable domain), which provides some protection against cross-site request forgery attacks (CSRF).\r\nIt takes three possible values: Strict, Lax, and None.With Strict, the cookie is sent only to the same site as the one that originated it;\r\nLax is similar, with an exception for when the user navigates to a URL from an external site, such as by following a link; None has no\r\nrestrictions on cross-site requests.",
"example": "unspecified"
},
"expirationDate": {
"type": "integer",
"description": "This unix timestamp formatted attribute is used to set persistent cookies. It signifies how long the browser should use the persistent\r\ncookie and when the cookie should be deleted.\r\nIf this attribute is not specified, then the lifetime of the cookie is the same as that of browser session, i.e.it will be a non-persistent\r\ncookie.",
"format": "int64",
"nullable": true,
"example": 1568986993
},
"session": {
"type": "boolean",
"description": "Session cookies are deleted when the current session ends. The browser defines when the \"current session\" ends, and some browsers use\r\nsession restoring when restarting, which can cause session cookies to last indefinitely long.",
"example": false
},
"storeId": {
"type": "string",
"description": "The ID of the cookie store containing this cookie.",
"nullable": true,
"example": "0"
}
},
"additionalProperties": false,
"description": "Representation of a cookie."
},
"BrowserSettings": {
"type": "object",
"properties": {
"arguments": {
"type": "array",
"items": {
"type": "string"
},
"description": "Command line arguments that can be passed to the browser at startup. This applies to both Chroma and Junglefox browsers.",
"nullable": true,
"example": ["--disable-notifications"]
},
"preferences": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Preference"
},
"description": "List of preferences for browsers that can be passed at startup. In case of Chromium-based options it will be a user profile preference. In\r\ncase of Firefox profiles it will be a preference.",
"nullable": true,
"example": [
{
"key": "signin.allowed_on_next_startup",
"value": false
}
]
},
"additionalOptions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Preference"
},
"description": "Special options available only in Kameleo, such as device scale factor for mobile emulated profiles. See the docs for more details.",
"nullable": true
}
},
"additionalProperties": false,
"description": "Extra settings and preferences that can be applied to the browser at startup."
},
"CanvasSpoofingType": {
"enum": ["intelligent", "noise", "block", "off"],
"type": "string",
"description": "Specifies how the canvas will be spoofed. Possible values:\r\n'intelligent': Use intelligent canvas spoofing. This will result non-unique canvas fingerprints.\r\n'noise': Add some noise to canvas generation.\r\n'block': Completely block the 2D API.\r\n'off': Turn off the spoofing, use the original settings."
},
"CloudTrafficQuota": {
"type": "object",
"properties": {
"currentUsage": {
"type": "integer",
"description": "Transferred data in bytes within the current period.",
"format": "int64"
},
"maximumLimit": {
"type": "integer",
"description": "Allowed data limit in bytes for the current period. A null value indicates an unlimited quota.",
"format": "int64",
"nullable": true
},
"nextResetAt": {
"type": "string",
"description": "Timestamp indicating when the current usage will reset to zero.",
"format": "date-time"
}
},
"additionalProperties": false
},
"CookieRequest": {
"required": ["domain", "name", "path", "value"],
"type": "object",
"properties": {
"domain": {
"minLength": 1,
"type": "string",
"description": "The domain attribute signifies the domain for which the cookie is valid and can be submitted with every request for this domain or its\r\nsubdomains. If this attribute is not specified, then the hostname of the originating server is used as the default value.",
"example": ".google.com"
},
"name": {
"type": "string",
"description": "The name for the Cookie.",
"example": "_ga"
},
"path": {
"minLength": 1,
"type": "string",
"description": "The path attribute indicates a URL path that must exist in the requested URL in order to send the Cookie header. The %x2F (\"/\") character\r\nis considered a directory separator, and subdirectories match as well.",
"example": "/gmail/about"
},
"value": {
"type": "string",
"description": "The value of the Cookie.",
"example": "GA1.2-3.982544754.9825342343"
},
"hostOnly": {
"type": "boolean",
"description": "Host Only cookie means that the cookie should be handled by the browser to the server only to the same host/server that firstly sent it to\r\nthe browser.",
"example": false
},
"httpOnly": {
"type": "boolean",
"description": "When this attribute is set, client-side scripts are not allowed to access the cookie.",
"example": true
},
"secure": {
"type": "boolean",
"description": "A cookie with the Secure attribute is sent to the server only with an encrypted request over the HTTPS protocol, never with unsecured HTTP,\r\nand therefore can't easily be accessed by a man-in-the-middle attacker. Insecure sites (with http: in the URL) can't set cookies with the\r\nSecure attribute.",
"example": true
},
"sameSite": {
"type": "string",
"description": "The sameSite attribute lets servers require that a cookie shouldn't be sent with cross-origin requests (where Site is defined by the\r\nregistrable domain), which provides some protection against cross-site request forgery attacks (CSRF).\r\nIt takes three possible values: Strict, Lax, and None.With Strict, the cookie is sent only to the same site as the one that originated it;\r\nLax is similar, with an exception for when the user navigates to a URL from an external site, such as by following a link; None has no\r\nrestrictions on cross-site requests.",
"nullable": true,
"example": "unspecified"
},
"expirationDate": {
"type": "integer",
"description": "This attribute is used to set persistent cookies. It signifies how long the browser should use the persistent cookie and when the cookie\r\nshould be deleted.\r\nIf this attribute is not specified, then the lifetime of the cookie is the same as that of browser session, i.e.it will be a non-persistent\r\ncookie.",
"format": "int64",
"nullable": true,
"example": 1568986993
}
},
"additionalProperties": false
},
"CreateFolderRequest": {
"required": ["name"],
"type": "object",
"properties": {
"name": {
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "Human readable name of the new folder.",
"example": "My first folder"
}
},
"additionalProperties": false
},
"CreateProfileRequest": {
"type": "object",
"properties": {
"fingerprintId": {
"type": "string",
"description": "The unique identifier of the fingerprint. This references the fingerprint which should be used to build the new profile.\r\nIf not provided, a fingerprint will be automatically selected using the recommended fingerprint search defaults, see: https://developer.kameleo.io/tutorials/filtering-fingerprints/",
"nullable": true,
"example": "555b894595b5cd242ead1533218a5ee93dd7c7ebfbff4dccb80fdb112f6cda27"
},
"name": {
"type": "string",
"description": "Sets a human-readable name for the profile, which is modifiable at any time.",
"nullable": true
},
"folderId": {
"type": "string",
"description": "Id of the folder the profile should be created in. If null or empty (00000000-0000-0000-0000-000000000000) the profile will be created in root.",
"format": "uuid",
"nullable": true,
"example": "0036135c-6f62-429b-a9db-fd541aca96a7"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Use tags to categorize profiles by labeling them accordingly.",
"nullable": true,
"example": ["facebook", "instagram"]
},
"canvas": {
"allOf": [
{
"$ref": "#/components/schemas/CanvasSpoofingType"
}
],
"description": "Specifies how the canvas will be spoofed. Possible values:\r\n'intelligent': Use intelligent canvas spoofing. This will result non-unique canvas fingerprints.\r\n'noise': Add some noise to canvas generation.\r\n'block': Completely block the 2D API.\r\n'off': Turn off the spoofing, use the original settings."
},
"webgl": {
"allOf": [
{
"$ref": "#/components/schemas/WebglSpoofingType"
}
],
"description": "Specifies how the WebGL will be spoofed. Possible values:\r\n'noise': Add some noise to the WebGL generation\r\n'block': Completely block the 3D API\r\n'off': Turn off the spoofing, use the original settings"
},
"webglMeta": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebglMetaChoice"
}
],
"description": "Sets how the WebGL Vendor and Renderer will be spoofed. Values can be 'automatic', 'manual', 'off'.",
"nullable": true
},
"audio": {
"allOf": [
{
"$ref": "#/components/schemas/AudioSpoofingType"
}
],
"description": "Specifies how the audio will be spoofed. Possible values:\r\n'noise': Add some noise to the Audio generation\r\n'block': Completely block the Audio API\r\n'off': Turn off the spoofing, use the original settings"
},
"timezone": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/TimezoneChoice"
}
],
"description": "Sets how the Timezone will be spoofed. Values can be 'automatic', 'manual', 'off'.",
"nullable": true
},
"geolocation": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/GeolocationChoice"
}
],
"description": "Sets how the Geolocation will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'.",
"nullable": true
},
"proxy": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ProxyChoice"
}
],
"description": "Sets the Proxy connection settings of the profile. Values can be 'none', 'http', 'socks5', 'ssh'. When it is not set to none, a server must\r\nbe provided.",
"nullable": true
},
"webRtc": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebRtcChoice"
}
],
"description": "Sets how the WebRTC will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'.",
"nullable": true
},
"fonts": {
"allOf": [
{
"$ref": "#/components/schemas/FontSpoofingType"
}
],
"description": "Specifies how the fonts will be spoofed. Possible values:\r\n'automatic': Spoof fonts based on the browser fingerpint.\r\n'off': Don't spoof fonts, use the real fonts of your machine."
},
"screen": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ScreenChoice"
}
],
"description": "Sets how the Screen will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a ScreenSize must be\r\nprovided.",
"nullable": true
},
"hardwareConcurrency": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/HardwareConcurrencyChoice"
}
],
"description": "Sets how the Hardware Concurrency will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a numeric value\r\n(1, 2, 4, 8, 12 or 16) must be provided.",
"nullable": true
},
"deviceMemory": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/DeviceMemoryChoice"
}
],
"description": "Sets how the Device Memory will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a numeric value (0.25,\r\n0.5, 1, 2, 4, 8, 16, 32) must be provided.",
"nullable": true
},
"language": {
"type": "string",
"description": "A language or a comma-separated list of languages for the profile.\r\nISO 639-1 language and optionally ISO 3166-1 region code.",
"nullable": true,
"example": "en-US,en"
},
"startPage": {
"type": "string",
"description": "This website will be opened in the browser when the profile launches.",
"format": "uri",
"nullable": true,
"example": "https://whoer.net/"
},
"passwordManager": {
"allOf": [
{
"$ref": "#/components/schemas/PasswordManagerType"
}
],
"description": "Defines whether the browser can save login credentials. Possible values are:\r\n'enabled': Credential saving is allowed.\r\n'disabled': Credential saving is blocked.",
"example": "enabled"
},
"extensions": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of abolute paths from where the profile should load extensions or addons when starting the browser. For chrome and edge use CRX3\r\nformat extensions. For firefox use signed xpi format addons.",
"nullable": true,
"example": ["C:\\Users\\Windows 10\\Kameleo Extensions\\necessary-extension.crx"]
},
"notes": {
"type": "string",
"description": "A free text including any notes written by the user.",
"nullable": true,
"example": "I used this profile for affiliate marketing."
},
"storage": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileStorageLocation"
}
],
"description": "Profile storage property which determines where the profile is stored. The default value is 'local'. When the value is changed the profile\r\nwill be migrated.",
"example": "local"
}
},
"additionalProperties": false
},
"DeleteFolderResponse": {
"required": ["deletedFolders", "deletedProfiles", "movedProfiles"],
"type": "object",
"properties": {
"deletedFolders": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Ids of the deleted folders."
},
"deletedProfiles": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Ids of the deleted profiles."
},
"movedProfiles": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProfilePreview"
},
"description": "Ids of the profiles moved to top-level."
}
},
"additionalProperties": false
},
"Device": {
"required": ["type"],
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Type of the device. Possible values are: 'desktop', 'mobile'.",
"example": "desktop"
},
"name": {
"type": "string",
"description": "Name of the device. This is only available for mobile profiles.",
"nullable": true,
"example": "Samsung SM-A705FN"
}
},
"additionalProperties": false
},
"DeviceMemoryChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/DeviceMemorySpoofingType"
}
],
"description": "Specifies how the deviceMemory will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the fingerprint.\r\n'manual': Manually set the value in the profile. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16, 32.\r\n'off': Turn off the spoofing, use the original settings."
},
"extra": {
"type": "number",
"format": "double",
"nullable": true
}
},
"additionalProperties": false
},
"DeviceMemorySpoofingType": {
"enum": ["automatic", "manual", "off"],
"type": "string",
"description": "Specifies how the deviceMemory will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the fingerprint.\r\n'manual': Manually set the value in the profile. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16, 32.\r\n'off': Turn off the spoofing, use the original settings."
},
"ErrorCode": {
"enum": [
"no_token",
"unauthorized",
"invalid_session",
"token_expired",
"authentication_failed",
"accountless_limit_reached",
"no_capability",
"no_cookies_capability",
"no_mobile_capability",
"no_proxy_test_capability",
"no_cloud_capability",
"no_local_capability",
"no_groups_capability",
"no_headless_capability",
"profile_not_found",
"profile_already_running",
"profile_not_running",
"profile_running",
"profile_locked",
"profile_syncing",
"profile_never_started",
"browser_engine_outdated",
"proxy_connection_issue",
"cloud_limit_reached",
"cloud_profile_not_exportable",
"profile_already_imported",
"incompatible_file",
"running_profiles_limit_reached",
"running_mobile_profiles_limit_reached",
"profile_minutes_limit_reached",
"downloaded_cloud_profile_bytes_limit_reached",
"folder_not_found",
"database_not_found",
"validation_failed",
"invalid_request",
"service_not_ready",
"rate_limit_exceeded",
"kernel_download_limit_reached",
"kernel_not_found",
"kernel_in_use",
"cdp_connection_failed",
"browser_instrumentation_disabled",
"vnc_not_supported",
"upload_failed",
"unexpected_error"
],
"type": "string"
},
"ExportProfileRequest": {
"required": ["path"],
"type": "object",
"properties": {
"path": {
"minLength": 1,
"type": "string",
"description": "Specifies the file path for exporting the profile.",
"example": "C:\\Users\\Windows 10\\Kameleo Profiles\\profile1.kameleo"
}
},
"additionalProperties": false,
"description": "Defines the target location for profile export."
},
"Fingerprint": {
"required": ["browser", "device", "fonts", "id", "os", "resolution", "userAgent", "version", "webglMeta"],
"type": "object",
"properties": {
"version": {
"type": "string",
"description": "The version of the fingerprint. As time passes new fingerprint versions will be introduced. It is recommended to use the latest one."
},
"id": {
"type": "string",
"description": "The unique identifier of the fingerprint. You can use this as a reference to create a new profile from this fingerprint.",
"example": "555b894595b5cd242ead1533218a5ee93dd7c7ebfbff4dccb80fdb112f6cda27"
},
"userAgent": {
"type": "string",
"description": "The user agent of the browser fingerprint.",
"example": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
},
"device": {
"required": ["type"],
"allOf": [
{
"$ref": "#/components/schemas/Device"
}
],
"description": "Information about the device of the fingerprint."
},
"os": {
"required": ["family", "version", "platform"],
"allOf": [
{
"$ref": "#/components/schemas/Os"
}
],
"description": "Information about the OS of the fingerprint."
},
"browser": {
"required": ["product", "major", "version"],
"allOf": [
{
"$ref": "#/components/schemas/Browser"
}
],
"description": "Information about the browser of the fingerprint."
},
"webglMeta": {
"required": ["vendor"],
"allOf": [
{
"$ref": "#/components/schemas/WebglMeta"
}
],
"description": "The GPU details extracted from WebGL parameters."
},
"resolution": {
"type": "string",
"description": "The screen size of the device in pixels.",
"example": "1920x1080"
},
"fonts": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of font types included in the profile.",
"example": ["Arial", "Tahoma"]
}
},
"additionalProperties": false,
"description": "Provides a full view of a fingerprint, which encapsulates real-world browser fingerprint configurations used to\r\ninstantiate virtual browser profiles."
},
"FingerprintPreview": {
"required": ["browser", "device", "fontsCount", "id", "os", "userAgent", "webglMeta"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The unique identifier of the fingerprint. You can use this as a reference to create a new profile from this fingerprint.",
"example": "BPID1CC227DG69B5M56E5DE4TW8P48B47NB8BB5967XEA501UZXP019FZGOX4A61"
},
"device": {
"required": ["type"],
"allOf": [
{
"$ref": "#/components/schemas/Device"
}
],
"description": "Information about the device of the fingerprint."
},
"os": {
"required": ["family", "version", "platform"],
"allOf": [
{
"$ref": "#/components/schemas/Os"
}
],
"description": "Information about the OS of the fingerprint."
},
"browser": {
"required": ["product", "major", "version"],
"allOf": [
{
"$ref": "#/components/schemas/Browser"
}
],
"description": "Information about the browser of the fingerprint."
},
"webglMeta": {
"required": ["vendor"],
"allOf": [
{
"$ref": "#/components/schemas/WebglMeta"
}
],
"description": "The GPU details of the fingerprint extracted from WebGL parameters."
},
"userAgent": {
"type": "string",
"description": "The user agent of the fingerprint."
},
"fontsCount": {
"type": "integer",
"description": "The number of fonts in the fingerprint.",
"format": "int32"
}
},
"additionalProperties": false,
"description": "Provides a summarized view of a fingerprint, which encapsulates real-world browser fingerprint configurations used to\r\ninstantiate virtual browser profiles. This preview aids in selecting the appropriate fingerprint from hundreds of thousands available."
},
"FolderResponse": {
"required": ["createdAt", "createdBy", "id", "lastModifiedAt", "lastModifiedBy", "name", "profiles", "shareAccesses"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A unique identifier of the folder.",
"format": "uuid",
"example": "a7cafbbe-6bc0-4575-8c6e-f1adf391f180"
},
"name": {
"type": "string",
"description": "The name of the folder.",
"example": "mystic-turtle"
},
"lastModifiedAt": {
"type": "string",
"description": "Timestamp of the last modification.",
"format": "date-time",
"example": "2020-05-02T03:10:32.2452701+10:00"
},
"lastModifiedBy": {
"type": "string",
"description": "Name of the user who last modified the folder.",
"example": "Demo user"
},
"createdAt": {
"type": "string",
"description": "Timestamp of the creation.",
"format": "date-time",
"example": "2020-05-02T03:10:32.2452701+10:00"
},
"createdBy": {
"type": "string",
"description": "Name of the user who created the folder.",
"example": "Demo user"
},
"profiles": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProfilePreview"
},
"description": "List of profiles in the current folder."
},
"shareAccesses": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ShareAccess"
},
"description": "List of users accessing this folder."
}
},
"additionalProperties": false
},
"FontSpoofingType": {
"enum": ["automatic", "off"],
"type": "string",
"description": "Specifies how the fonts will be spoofed. Possible values:\r\n'automatic': Spoof fonts based on the browser fingerpint.\r\n'off': Don't spoof fonts, use the real fonts of your machine."
},
"GeolocationChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/GeolocationSpoofingType"
}
],
"description": "Specifies how the geolocation will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the IP address\r\n'manual': Manually set the longitude and latitude in the profile\r\n'block': Completely block the Geolocation API\r\n'off': Turn off the spoofing, use the original settings"
},
"extra": {
"required": ["latitude", "longitude"],
"allOf": [
{
"$ref": "#/components/schemas/GeolocationSpoofingOptions"
}
],
"description": "When the Geolocation spoofing is set to manual these extra settings will be used as well.",
"nullable": true
}
},
"additionalProperties": false
},
"GeolocationSpoofingOptions": {
"required": ["latitude", "longitude"],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "From -90 to 90",
"format": "float",
"example": 59.43984
},
"longitude": {
"type": "number",
"description": "From -180 to 180",
"format": "float",
"example": 24.75815
}
},
"additionalProperties": false,
"description": "When the Geolocation spoofing is set to manual these extra settings will be used as well."
},
"GeolocationSpoofingType": {
"enum": ["automatic", "manual", "block", "off"],
"type": "string",
"description": "Specifies how the geolocation will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the IP address\r\n'manual': Manually set the longitude and latitude in the profile\r\n'block': Completely block the Geolocation API\r\n'off': Turn off the spoofing, use the original settings"
},
"GroupRole": {
"required": ["description", "id", "name"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier of the role.",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Name of the role."
},
"description": {
"type": "string",
"description": "Description of the role."
}
},
"additionalProperties": false
},
"HardwareConcurrencyChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/HardwareConcurrencySpoofingType"
}
],
"description": "Specifies how the hardwareConcurrency will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the fingerprint.\r\n'manual': Manually set the value in the profile. Valid values: 1, 2, 4, 8, 12, 16.\r\n'off': Turn off the spoofing, use the original settings."
},
"extra": {
"type": "integer",
"format": "int32",
"nullable": true
}
},
"additionalProperties": false
},
"HardwareConcurrencySpoofingType": {
"enum": ["automatic", "manual", "off"],
"type": "string",
"description": "Specifies how the hardwareConcurrency will be spoofed. Possible values:\r\n'automatic': Automatically set the values based on the fingerprint.\r\n'manual': Manually set the value in the profile. Valid values: 1, 2, 4, 8, 12, 16.\r\n'off': Turn off the spoofing, use the original settings."
},
"ImportProfileRequest": {
"required": ["path"],
"type": "object",
"properties": {
"path": {
"minLength": 1,
"type": "string",
"description": "The file path from which the profile will be imported.",
"example": "C:\\Users\\Windows 10\\Kameleo Profiles\\profile1.kameleo"
}
},
"additionalProperties": false,
"description": "Specifies the source location for profile import."
},
"KernelResponse": {
"required": ["browser", "builtAt", "downloadSize", "id", "isInUse", "isInstalled", "isMarkedForRemoval", "platform", "version"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier of the kernel.",
"format": "uuid"
},
"platform": {
"minLength": 1,
"type": "string",
"description": "The operating system this kernel supports (e.g: win-x64, osx-arm64)."
},
"browser": {
"minLength": 1,
"type": "string",
"description": "The browser this kernel contains (e.g: chroma, junglefox)."
},
"version": {
"type": "string",
"description": "Version of the browser."
},
"builtAt": {
"type": "string",
"description": "Build timestamp of the kernel.",
"format": "date-time"
},
"downloadSize": {
"type": "integer",
"description": "Size of the download package in bytes.",
"format": "int64"
},
"diskSize": {
"type": "integer",
"description": "Size of the extracted package on the local file system in bytes or null if the kernel is not installed.",
"format": "int64",
"nullable": true
},
"isInstalled": {
"type": "boolean",
"description": "Flag indicating if the kernel is locally available (true) or it has to be installed before usage (false)."
},
"isInUse": {
"type": "boolean",
"description": "Flag indicating if the kernel is currently in use."
},
"isMarkedForRemoval": {
"type": "boolean",
"description": "Flag indicating that the kernel will be removed from the local file system when it is not in use."
}
},
"additionalProperties": false
},
"ListFoldersResponse": {
"required": ["folders", "profiles"],
"type": "object",
"properties": {
"folders": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FolderResponse"
},
"description": "List of top-level folders, each folder may contain nested folders and cloud profiles."
},
"profiles": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProfilePreview"
},
"description": "List of profiles not associated with any folder. This includes both cloud and local profiles."
}
},
"additionalProperties": false
},
"Os": {
"required": ["family", "platform", "version"],
"type": "object",
"properties": {
"family": {
"type": "string",
"description": "Specifies the operating system family. Possible values are 'windows', 'macos', 'linux', 'android', 'ios'.",
"example": "windows"
},
"version": {
"type": "string",
"description": "The specific version of the OS. For example it helps you determine the exact version of the macOS.",
"example": "10.15.4"
},
"platform": {
"type": "string",
"description": "The OS's platform, indicating the processor architecture (e.g., 64-bit, 32-bit)",
"example": "64"
}
},
"additionalProperties": false
},
"PasswordManagerType": {
"enum": ["enabled", "disabled"],
"type": "string",
"description": "Defines whether the browser can save login credentials. Possible values are:\r\n'enabled': Credential saving is allowed.\r\n'disabled': Credential saving is blocked."
},
"Preference": {
"required": ["key", "value"],
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Key of the preference",
"example": "profile.managed_default_content_settings.images"
},
"value": {
"description": "Value of the preference. It can a string or a boolean or an integer",
"example": 2
}
},
"additionalProperties": false,
"description": "Represents a Key-Value pair where Value can be a string or a boolean or an integer"
},
"ProblemDetails": {
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"type": "integer",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
}
},
"additionalProperties": {}
},
"ProblemResponse": {
"required": ["errorCode", "status", "title"],
"type": "object",
"properties": {
"status": {
"type": "integer",
"description": "The HTTP status code generated by the origin server for this occurrence of the problem.",
"format": "int32"
},
"errorCode": {
"allOf": [
{
"$ref": "#/components/schemas/ErrorCode"
}
],
"description": "A machine-readable error code that identifies the specific error condition. This can be used by clients to programmatically handle different error scenarios."
},
"type": {
"type": "string",
"description": "A URI reference that identifies the problem type.",
"nullable": true
},
"title": {
"type": "string",
"description": "A short, human-readable summary of the problem type."
},
"detail": {
"type": "string",
"description": "A human-readable explanation specific to this occurrence of the problem.",
"nullable": true
},
"instance": {
"type": "string",
"description": "A URI reference that identifies the specific occurrence of the problem.",
"nullable": true
},
"errors": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "The validation errors, if any. The keys are field names and the values are arrays of error messages.",
"nullable": true
}
},
"additionalProperties": {}
},
"ProfileLifetimeState": {
"enum": ["created", "starting", "running", "terminating", "terminated", "locked", "loading", "unknown"],
"type": "string",
"description": "Represents the lifetime states of a profile, indicating which actions\r\ncan be performed with the associated browser engine at each state. Possible values are:\r\n- Created: Profile is created; the associated browser engine is not started.\r\n- Starting: The associated browser engine is starting.\r\n- Running: The associated browser engine is currently running.\r\n- Terminating: The associated browser engine is in the process of terminating.\r\n- Terminated: The associated browser engine is not running but has been started at least once.\r\n- Locked: The profile is currently being used by another user.\r\n- Loading: The profile data or the browser engine is syncing with the cloud storage.\r\n- Unknown: State of the profile is undefined."
},
"ProfileMinutesQuota": {
"type": "object",
"properties": {
"currentUsage": {
"type": "string",
"format": "date-span"
},
"maximumLimit": {
"type": "string",
"format": "date-span",
"nullable": true
},
"nextResetAt": {
"type": "string",
"format": "date-time"
}
},
"additionalProperties": false
},
"ProfilePreview": {
"required": ["browser", "createdAt", "device", "id", "language", "name", "os", "proxy", "status", "tags"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A unique identifier of the profile",
"format": "uuid",
"example": "a7cafbbe-6bc0-4575-8c6e-f1adf391f180"
},
"name": {
"type": "string",
"description": "The name of the profile",
"example": "mystic-turtle"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Profile tags",
"example": ["facebook", "instagram"]
},
"proxy": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ProxyChoice"
}
],
"description": "Proxy connection settings of the profiles. Values can be 'none', 'http', 'socks5', 'ssh'. When it is not set to none, a server is provided."
},
"createdAt": {
"type": "string",
"description": "Date when the profile was created.",
"format": "date-time",
"example": "2020-05-02T03:10:32.2452701+10:00"
},
"device": {
"required": ["type"],
"allOf": [
{
"$ref": "#/components/schemas/Device"
}
],
"description": "Device information about the profile. This is derived from the fingerprint."
},
"os": {
"required": ["family", "version", "platform"],
"allOf": [
{
"$ref": "#/components/schemas/Os"
}
],
"description": "Information about the OS of the profile. This is derived from the fingerprint."
},
"browser": {
"required": ["product", "major", "version"],
"allOf": [
{
"$ref": "#/components/schemas/Browser"
}
],
"description": "Information about the browser of the profile. This is derived from the fingerprint."
},
"language": {
"type": "string",
"description": "A language or a comma-separated list of languages for the profile.\r\nISO 639-1 language and optionally ISO 3166-1 region code.",
"example": "en-US,en"
},
"status": {
"required": ["lifetimeState"],
"allOf": [
{
"$ref": "#/components/schemas/StatusResponse"
}
],
"description": "Status information about the profile."
},
"storage": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileStorageLocation"
}
],
"description": "Profile storage property which determines where the profile is stored. The default value is 'local'. When the value is changed the profile\r\nwill be migrated.",
"example": "local"
},
"folderId": {
"type": "string",
"description": "A unique identifier of the containing folder, or empty (00000000-0000-0000-0000-000000000000) if not in a folder.\r\nThis will always be empty for locally stored profiles, as only cloud profiles can be added to folders.",
"format": "uuid",
"nullable": true,
"example": "c7aafbbe-b6c0-5475-c66e-1fadf39180f1"
}
},
"additionalProperties": false,
"description": "A preview about the profile with some of its properties."
},
"ProfileResponse": {
"required": [
"audio",
"canvas",
"createdAt",
"deviceMemory",
"extensions",
"fingerprint",
"fonts",
"geolocation",
"hardwareConcurrency",
"id",
"language",
"name",
"notes",
"passwordManager",
"proxy",
"screen",
"startPage",
"status",
"tags",
"timezone",
"webRtc",
"webgl",
"webglMeta"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "A unique identifier of the profile",
"format": "uuid",
"example": "a7cafbbe-6bc0-4575-8c6e-f1adf391f180"
},
"name": {
"type": "string",
"description": "Profile name property. The value obtained by file name for existing profiles. For new profiles the value is generated by a random name\r\ngenerator.",
"example": "mystic-turtle"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Profile tags",
"example": ["facebook", "instagram"]
},
"createdAt": {
"type": "string",
"description": "Date when the profile was created.",
"format": "date-time",
"example": "2020-05-02T03:10:32.2452701+10:00"
},
"fingerprint": {
"required": ["version", "id", "userAgent", "device", "os", "browser", "webglMeta", "resolution", "fonts"],
"allOf": [
{
"$ref": "#/components/schemas/Fingerprint"
}
],
"description": "Provides a full view of a fingerprint, which encapsulates real-world browser fingerprint configurations used to\r\ninstantiate virtual browser profiles."
},
"canvas": {
"allOf": [
{
"$ref": "#/components/schemas/CanvasSpoofingType"
}
],
"description": "Specifies how the canvas will be spoofed. Possible values:\r\n'intelligent': Use intelligent canvas spoofing. This will result non-unique canvas fingerprints.\r\n'noise': Add some noise to canvas generation.\r\n'block': Completely block the 2D API.\r\n'off': Turn off the spoofing, use the original settings."
},
"webgl": {
"allOf": [
{
"$ref": "#/components/schemas/WebglSpoofingType"
}
],
"description": "Specifies how the WebGL will be spoofed. Possible values:\r\n'noise': Add some noise to the WebGL generation\r\n'block': Completely block the 3D API\r\n'off': Turn off the spoofing, use the original settings"
},
"webglMeta": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebglMetaChoice"
}
],
"description": "Sets how the WebGL Vendor and Renderer will be spoofed. Possible values:\r\n'automatic': The vendor and renderer values comes from the fingerprint.\r\n'manual': Manually set the vendor and renderer values.\r\n'off': Turn off the spoofing, use the original settings"
},
"audio": {
"allOf": [
{
"$ref": "#/components/schemas/AudioSpoofingType"
}
],
"description": "Specifies how the audio will be spoofed. Possible values:\r\n'noise': Add some noise to the Audio generation\r\n'block': Completely block the Audio API\r\n'off': Turn off the spoofing, use the original settings"
},
"timezone": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/TimezoneChoice"
}
],
"description": "Sets how the Timezone will be spoofed. Values can be 'automatic', 'manual', 'off'."
},
"geolocation": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/GeolocationChoice"
}
],
"description": "Sets how the Geolocation will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'."
},
"proxy": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ProxyChoice"
}
],
"description": "Proxy connection settings of the profiles. Values can be 'none', 'http', 'socks5', 'ssh'. When it is not set to none, a server is provided."
},
"webRtc": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebRtcChoice"
}
],
"description": "Sets how the WebRTC will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'."
},
"fonts": {
"allOf": [
{
"$ref": "#/components/schemas/FontSpoofingType"
}
],
"description": "Specifies how the fonts will be spoofed. Possible values:\r\n'automatic': Spoof fonts based on the browser fingerpint.\r\n'off': Don't spoof fonts, use the real fonts of your machine."
},
"screen": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ScreenChoice"
}
],
"description": "Sets how the Screen will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a ScreenSize must be provided"
},
"hardwareConcurrency": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/HardwareConcurrencyChoice"
}
],
"description": "Sets how the Hardware Concurrency will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a\r\nHardwareConcurrencyType must be provided (valid values:1, 2, 4, 8, 12, 16)"
},
"deviceMemory": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/DeviceMemoryChoice"
}
],
"description": "Sets the level of device memory spoofing. Values can be 'automatic', 'manual', 'off'.\r\nWhen value is set to manual, a specific amount of device memory must be provided (valid values: 0.25, 0.5, 1, 2, 4, 8, 16, 32)",
"example": {
"value": "automatic"
}
},
"language": {
"type": "string",
"description": "A language or a comma-separated list of languages for the profile.\r\nISO 639-1 language and optionally ISO 3166-1 region code.",
"example": "en-US,en"
},
"startPage": {
"type": "string",
"description": "This website will be opened in the browser when the profile launches.",
"example": "https://whoer.net/"
},
"passwordManager": {
"allOf": [
{
"$ref": "#/components/schemas/PasswordManagerType"
}
],
"description": "Defines whether the browser can save login credentials. Possible values are:\r\n'enabled': Credential saving is allowed.\r\n'disabled': Credential saving is blocked.",
"example": "enabled"
},
"extensions": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of extensions or addons that will be loaded to the profile when the profile is started. For chrome and edge use CRX3 format\r\nextensions. For firefox use signed xpi format addons.",
"example": ["C:\\Users\\Windows 10\\Kameleo Extensions\\necessary-extension.crx"]
},
"notes": {
"type": "string",
"description": "A free text including any notes written by the user.",
"example": "I used this profile for ad verification."
},
"status": {
"required": ["lifetimeState"],
"allOf": [
{
"$ref": "#/components/schemas/StatusResponse"
}
],
"description": "Status information about the profile."
},
"storage": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileStorageLocation"
}
],
"description": "Profile storage property which determines where the profile is stored. The default value is 'local'. When the value is changed the profile\r\nwill be migrated.",
"example": "local"
},
"folderId": {
"type": "string",
"description": "A unique identifier of the containing folder or empty (00000000-0000-0000-0000-000000000000) if it is not in folder.",
"format": "uuid",
"nullable": true,
"example": "c7aafbbe-b6c0-5475-c66e-1fadf39180f1"
}
},
"additionalProperties": false
},
"ProfileStorageLocation": {
"enum": ["local", "cloud"],
"type": "string"
},
"ProxyChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/ProxyConnectionType"
}
],
"description": "Proxy connection settings of the profiles. Possible values:\r\n'none': Direct connection without any proxy.\r\n'http': Use a HTTP proxy for upstream communication.\r\n'socks5': Use a SOCKS5 proxy for upstream communication.\r\n'ssh': Use an SSH connection for upstream communication. Basically a SOCKS5 proxy created at the given SSH host."
},
"extra": {
"required": ["host", "port"],
"allOf": [
{
"$ref": "#/components/schemas/Server"
}
],
"description": "Represents a server connection. It can be used as a proxy server connection as well.",
"nullable": true
}
},
"additionalProperties": false
},
"ProxyConnectionType": {
"enum": ["none", "http", "socks5", "ssh"],
"type": "string",
"description": "Proxy connection settings of the profiles. Possible values:\r\n'none': Direct connection without any proxy.\r\n'http': Use a HTTP proxy for upstream communication.\r\n'socks5': Use a SOCKS5 proxy for upstream communication.\r\n'ssh': Use an SSH connection for upstream communication. Basically a SOCKS5 proxy created at the given SSH host."
},
"ProxyTestResultStatus": {
"enum": ["success", "partial_success", "failure"],
"type": "string",
"description": "Summarizes the overall outcome of a proxy connectivity test. Possible values:\r\n'success': Every test step passed.\r\n'partial_success': The website could be reached through at least one of IPv4, IPv6 or DNS name, and the IP location lookup succeeded.\r\n'failure': None of the connectivity checks succeeded."
},
"ProxyTestStepResponse": {
"required": ["comment", "name", "step", "successful"],
"type": "object",
"properties": {
"step": {
"allOf": [
{
"$ref": "#/components/schemas/ProxyValidationStep"
}
],
"description": "Identifier of the executed test step.",
"example": ""
},
"name": {
"type": "string",
"description": "The name of the executed test case.",
"example": "Testing direct internet connectivity by pinging a remote host"
},
"successful": {
"type": "boolean",
"description": "Whether the test was successful or not.",
"example": true
},
"comment": {
"type": "string",
"description": "Any additional details about the test case, such as error messages.",
"example": "Proxy authentication failed"
}
},
"additionalProperties": false
},
"ProxyValidationStep": {
"enum": ["ssh_connection", "direct_ping", "direct_https", "proxy_ipv4", "proxy_ipv6", "proxy_website", "proxy_location"],
"type": "string"
},
"QuotaStatistics": {
"required": ["currentUsage", "maximumLimit"],
"type": "object",
"properties": {
"currentUsage": {
"type": "integer",
"description": "Indicates the current usage, always a non-negative value.",
"format": "int32",
"readOnly": true
},
"maximumLimit": {
"type": "integer",
"description": "Indicates the maximum permitted value, with -1 implying no limit.",
"format": "int32",
"readOnly": true
}
},
"additionalProperties": false
},
"RunningProfiles": {
"required": ["tenant", "user"],
"type": "object",
"properties": {
"user": {
"required": ["automated", "manual", "mobile", "total"],
"allOf": [
{
"$ref": "#/components/schemas/RunningProfilesStatistics"
}
],
"description": "Current usage and maximum limit of running automated, manual, mobile and total profiles for the logged-in user."
},
"tenant": {
"required": ["automated", "manual", "mobile", "total"],
"allOf": [
{
"$ref": "#/components/schemas/RunningProfilesStatistics"
}
],
"description": "Current usage and maximum limit of running automated, manual, mobile and total profiles across the tenant."
}
},
"additionalProperties": false
},
"RunningProfilesStatistics": {
"required": ["automated", "manual", "mobile", "total"],
"type": "object",
"properties": {
"automated": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Quota usage of the profiles that are running with an automation framework."
},
"manual": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Quota usage of the profiles that are running manually (were started from GUI or API)."
},
"mobile": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Quota usage of the profiles having mobile fingerprints."
},
"total": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Quota usage of the profiles that are running either manually or with an automation framework."
}
},
"additionalProperties": false
},
"ScreenChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/ScreenSpoofingType"
}
],
"description": "Specifies how the screen will be spoofed. Possible values:\r\n'automatic': Automatically override the screen resolution based on the fingerprint.\r\n'manual': Manually override the screen resolution.\r\n'off': Turn off the spoofing, use the original settings."
},
"extra": {
"type": "string",
"description": "The screen size of the device in CSS pixels.\r\nCSS values correspond to bigger physical pixel values when scaled, so provide values accordingly. (Kameleo's default scaling is 1x for desktop and 2x for mobile profiles.)\r\nExamples for 1080p: 1920x1080 (desktop), 412x732 (mobile).",
"nullable": true
}
},
"additionalProperties": false
},
"ScreenSpoofingType": {
"enum": ["automatic", "manual", "off"],
"type": "string",
"description": "Specifies how the screen will be spoofed. Possible values:\r\n'automatic': Automatically override the screen resolution based on the fingerprint.\r\n'manual': Manually override the screen resolution.\r\n'off': Turn off the spoofing, use the original settings."
},
"Server": {
"required": ["host", "port"],
"type": "object",
"properties": {
"host": {
"type": "string",
"description": "Gets or sets the hostname where the service is provided from.",
"example": "127.0.0.1"
},
"port": {
"type": "integer",
"description": "Gets or sets the port where the service is provided from.",
"format": "int32",
"example": 9951
},
"id": {
"type": "string",
"description": "Gets or sets the identity information provided for the service. This could be a custom id or username or anything which identifies a\r\nresource on the remote service. Use it as a proxy username. This field is optional.",
"nullable": true,
"example": "username"
},
"secret": {
"type": "string",
"description": "Gets or sets the shared secret between the client and the service provider. Use it as a proxy password. This field is optional.",
"nullable": true,
"example": "password"
}
},
"additionalProperties": false,
"description": "Represents a server connection. It can be used as a proxy server connection as well."
},
"ShareAccess": {
"required": ["role", "sharedAt", "user"],
"type": "object",
"properties": {
"user": {
"required": ["id", "name", "email"],
"allOf": [
{
"$ref": "#/components/schemas/User"
}
],
"description": "User accessing this folder."
},
"role": {
"required": ["id", "name", "description"],
"allOf": [
{
"$ref": "#/components/schemas/GroupRole"
}
],
"description": "Level of access to the folder."
},
"sharedAt": {
"type": "string",
"description": "Timestamp when the acess was granted to the user.",
"format": "date-time"
}
},
"additionalProperties": false
},
"ShareAccessRequest": {
"required": ["roleId", "userId"],
"type": "object",
"properties": {
"roleId": {
"type": "string",
"description": "Id of the selected role.",
"format": "uuid"
},
"userId": {
"type": "string",
"description": "Id of the selected user.",
"format": "uuid"
}
},
"additionalProperties": false
},
"ShareGroupRequest": {
"required": ["shareAccesses"],
"type": "object",
"properties": {
"shareAccesses": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ShareAccessRequest"
},
"description": "List of share accesses to the folder."
}
},
"additionalProperties": false
},
"SharingOptionsResponse": {
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
},
"description": "List of users in your team.",
"nullable": true
},
"roles": {
"type": "array",
"items": {
"$ref": "#/components/schemas/GroupRole"
},
"description": "List of roles you can give the users.",
"nullable": true
}
},
"additionalProperties": false
},
"StatusResponse": {
"required": ["lifetimeState"],
"type": "object",
"properties": {
"lifetimeState": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileLifetimeState"
}
],
"description": "Represents the lifetime states of a profile, indicating which actions\r\ncan be performed with the associated browser engine at each state. Possible values are:\r\n- Created: Profile is created; the associated browser engine is not started.\r\n- Starting: The associated browser engine is starting.\r\n- Running: The associated browser engine is currently running.\r\n- Terminating: The associated browser engine is in the process of terminating.\r\n- Terminated: The associated browser engine is not running but has been started at least once.\r\n- Locked: The profile is currently being used by another user.\r\n- Loading: The profile data or the browser engine is syncing with the cloud storage.\r\n- Unknown: State of the profile is undefined.",
"example": "terminated"
}
},
"additionalProperties": false,
"description": "Status information about the profile"
},
"TestProxyRequest": {
"required": ["proxy"],
"type": "object",
"properties": {
"proxy": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ProxyChoice"
}
],
"description": "Sets the Proxy connection settings to test. Values can be 'none', 'http', 'socks5', 'ssh'. When it is not set to none, a server must be\r\nprovided."
}
},
"additionalProperties": false
},
"TestProxyResponse": {
"required": ["result", "steps"],
"type": "object",
"properties": {
"result": {
"allOf": [
{
"$ref": "#/components/schemas/ProxyTestResultStatus"
}
],
"description": "Summarizes the overall outcome of a proxy connectivity test. Possible values:\r\n'success': Every test step passed.\r\n'partial_success': The website could be reached through at least one of IPv4, IPv6 or DNS name, and the IP location lookup succeeded.\r\n'failure': None of the connectivity checks succeeded.",
"example": "success"
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ProxyTestStepResponse"
},
"description": "A list containing each individual test step performed while testing the proxy connection."
}
},
"additionalProperties": false
},
"TimezoneChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/TimezoneSpoofingType"
}
],
"description": "Specifies how the timezone will be spoofed. Possble values:\r\n'automatic': Timezone is automatically set by the IP\r\n'manual': Timezone is manually overridden in the profile\r\n'off': Turn off the spoofing, use the original settings"
},
"extra": {
"type": "string",
"description": "When the Timezone spoofing is set to manual the timezone in Iana format is required. For example: America/Grenada",
"nullable": true
}
},
"additionalProperties": false
},
"TimezoneSpoofingType": {
"enum": ["automatic", "manual", "off"],
"type": "string",
"description": "Specifies how the timezone will be spoofed. Possble values:\r\n'automatic': Timezone is automatically set by the IP\r\n'manual': Timezone is manually overridden in the profile\r\n'off': Turn off the spoofing, use the original settings"
},
"UpdateFolderRequest": {
"required": ["name"],
"type": "object",
"properties": {
"name": {
"maxLength": 100,
"minLength": 1,
"type": "string",
"description": "Human readable name of the folder.",
"example": "My renamed folder"
}
},
"additionalProperties": false
},
"UpdateProfileRequest": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Profile name property. The value obtained by file name for existing profiles. For new profiles the value is generated by a random name\r\ngenerator.",
"nullable": true
},
"folderId": {
"type": "string",
"description": "Id of the folder the profile should be moved to. If null it won't be changed, if empty (00000000-0000-0000-0000-000000000000) it will be moved to root.",
"format": "uuid",
"nullable": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Profile tags",
"nullable": true,
"example": ["facebook", "instagram"]
},
"canvas": {
"allOf": [
{
"$ref": "#/components/schemas/CanvasSpoofingType"
}
],
"description": "Sets how the canvas will be spoofed. Values can be 'intelligent', 'noise', 'block', 'off'.",
"nullable": true
},
"webgl": {
"allOf": [
{
"$ref": "#/components/schemas/WebglSpoofingType"
}
],
"description": "Sets how the WebGL will be spoofed. Values can be 'noise', 'block', 'off'.",
"nullable": true
},
"webglMeta": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebglMetaChoice"
}
],
"description": "Sets how the WebGL Vendor and Renderer will be spoofed. Possible values:\r\n'automatic': The vendor and renderer values comes from the fingerprint.\r\n'manual': Manually set the vendor and renderer values.\r\n'off': Turn off the spoofing, use the original settings",
"nullable": true
},
"audio": {
"allOf": [
{
"$ref": "#/components/schemas/AudioSpoofingType"
}
],
"description": "Sets how the Audio will be spoofed. Values can be 'noise', 'block', 'off'.",
"nullable": true
},
"timezone": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/TimezoneChoice"
}
],
"description": "Sets how the Timezone will be spoofed. Values can be 'automatic', 'manual', 'off'.",
"nullable": true
},
"geolocation": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/GeolocationChoice"
}
],
"description": "Sets how the Geolocation will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'.",
"nullable": true
},
"proxy": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ProxyChoice"
}
],
"description": "Proxy connection settings of the profiles. Values can be 'none', 'http', 'socks5', 'ssh'. When it is not set to none, a server must be\r\nprovided.",
"nullable": true
},
"webRtc": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/WebRtcChoice"
}
],
"description": "Sets how the WebRTC will be spoofed. Values can be 'automatic', 'manual', 'block', 'off'.",
"nullable": true
},
"fonts": {
"allOf": [
{
"$ref": "#/components/schemas/FontSpoofingType"
}
],
"description": "Sets how the Fonts will be spoofed. Values can be 'enabled', 'disabled'.",
"nullable": true
},
"screen": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/ScreenChoice"
}
],
"description": "Sets how the Screen will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a ScreenSize must be provided",
"nullable": true
},
"hardwareConcurrency": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/HardwareConcurrencyChoice"
}
],
"description": "Sets how the Hardware Concurrency will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a\r\nHardwareConcurrencyType must be provided (valid values:1, 2, 4, 8, 12, 16)",
"nullable": true
},
"deviceMemory": {
"required": ["value"],
"allOf": [
{
"$ref": "#/components/schemas/DeviceMemoryChoice"
}
],
"description": "Sets how the Device Memory will be spoofed. Values can be 'automatic', 'manual', 'off'. When value is set to manual, a DeviceMemoryType\r\nmust be provided (valid values: 0.25, 0.5, 1, 2, 4, 8, 16, 32)",
"nullable": true
},
"language": {
"type": "string",
"description": "A language or a comma-separated list of languages for the profile.\r\nISO 639-1 language and optionally ISO 3166-1 region code.",
"nullable": true,
"example": "en-US,en"
},
"startPage": {
"type": "string",
"description": "This website will be opened in the browser when the profile launches.",
"format": "uri",
"nullable": true,
"example": "https://kameleo.io/"
},
"passwordManager": {
"allOf": [
{
"$ref": "#/components/schemas/PasswordManagerType"
}
],
"description": "Indicates whether the browser supports saving login credentials.",
"nullable": true,
"example": "enabled"
},
"extensions": {
"type": "array",
"items": {
"type": "string"
},
"description": "A list of extensions or addons should be loaded to the browser when starting the profile. For extensions that are added now, it should be\r\nan absolute path.\r\nFor extensions already added to the profile in a previous update, the name is only enough.\r\nFor chrome and edge use CRX3 format extensions. For firefox use signed xpi format addons.",
"nullable": true,
"example": ["C:\\Users\\Windows 10\\Kameleo Extensions\\necessary-extension.crx"]
},
"notes": {
"type": "string",
"description": "A free text including any notes written by the user.",
"nullable": true,
"example": "I used this profile for affiliate marketing."
},
"storage": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileStorageLocation"
}
],
"description": "Profile storage property which determines where the profile is stored. The default value is 'local'. When the value is changed the profile\r\nwill be migrated.",
"nullable": true,
"example": "local"
}
},
"additionalProperties": false
},
"User": {
"required": ["email", "id", "name"],
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier of the user.",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Dispaly name of the user."
},
"email": {
"type": "string",
"description": "Email address of the user."
}
},
"additionalProperties": false
},
"UserInfoResponse": {
"required": [
"capabilities",
"cloudStorage",
"cloudTraffic",
"displayName",
"email",
"emailConfirmed",
"gracePeriod",
"hasTeamSubscription",
"lastAppLogin",
"localStorage",
"plan",
"profileMinutes",
"runningProfiles",
"subscriptionEnd",
"userId",
"version",
"workspaceFolder"
],
"type": "object",
"properties": {
"userId": {
"type": "string",
"description": "Unique identifier for the user in Guid v4 format.",
"format": "uuid",
"example": "054c78aa-efef-4a15-a348-cbf1766f8970"
},
"displayName": {
"type": "string",
"description": "The display name of the user, updated on each login.",
"example": "user"
},
"email": {
"type": "string",
"description": "The email address of the user.",
"example": "user@email.com"
},
"emailConfirmed": {
"type": "boolean",
"description": "Indicates if the user's email address has been verified.",
"example": true
},
"subscriptionEnd": {
"type": "string",
"description": "The subscription end date for the user. If the user is part of a team, this is the team's subscription end date.",
"format": "date-time",
"example": "2038-01-19T03:14:07Z"
},
"plan": {
"type": "string",
"description": "The subscription plan associated with the user.",
"example": "free"
},
"capabilities": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of features available to the user based on their current subscription or their team's subscription.",
"example": ["clone_profile", "cloud", "cookie", "groups", "impex", "local", "mobile", "proxy_test", "start", "upgrade_profile"]
},
"gracePeriod": {
"type": "boolean",
"description": "Indicates if the user's subscription is currently in a grace period and requires instant renewal.",
"example": true
},
"lastAppLogin": {
"type": "string",
"description": "The date and time of the user's last login via the app.",
"format": "date-time",
"example": "2020-01-01T00:00:00Z"
},
"version": {
"type": "string",
"description": "The version of the app.",
"example": "5.0.0"
},
"workspaceFolder": {
"type": "string",
"description": "Path to the user's workspace folder where profiles are stored. Modifying these files outside of Kameleo is strictly prohibited.",
"example": "C:\\Users\\Tomi\\AppData\\Local\\Programs\\Kameleo\\Workspace\\cb2bdd5e-6777-4d9b-9573-d3209186f686"
},
"localStorage": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Current usage and maximum limit for local profiles."
},
"cloudStorage": {
"required": ["currentUsage", "maximumLimit"],
"allOf": [
{
"$ref": "#/components/schemas/QuotaStatistics"
}
],
"description": "Current usage and maximum limit for cloud profiles."
},
"hasTeamSubscription": {
"type": "boolean",
"description": "Indicates if the user has a team subscription. This can also be true if the user does not have any team members yet.",
"example": true
},
"teamId": {
"type": "string",
"description": "The team ID if the user is part of a team.",
"format": "uuid",
"nullable": true,
"example": "099c78aa-efef-4a15-a348-cbf1766f8000"
},
"teamRole": {
"type": "string",
"description": "The user's role within the team, such as 'owner' or 'member'.",
"nullable": true,
"example": "member"
},
"runningProfiles": {
"required": ["user", "tenant"],
"allOf": [
{
"$ref": "#/components/schemas/RunningProfiles"
}
],
"description": "Current usage and maximum limit of the running profiles."
},
"profileMinutes": {
"allOf": [
{
"$ref": "#/components/schemas/ProfileMinutesQuota"
}
],
"description": "Current usage and maximum limit of profile minutes across the tenant."
},
"cloudTraffic": {
"allOf": [
{
"$ref": "#/components/schemas/CloudTrafficQuota"
}
],
"description": "Current usage and maximum limit of cloud traffic quota across the tenant."
}
},
"additionalProperties": false
},
"ValidationProblemDetails": {
"type": "object",
"properties": {
"type": {
"type": "string",
"nullable": true
},
"title": {
"type": "string",
"nullable": true
},
"status": {
"type": "integer",
"format": "int32",
"nullable": true
},
"detail": {
"type": "string",
"nullable": true
},
"instance": {
"type": "string",
"nullable": true
},
"errors": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"additionalProperties": {}
},
"WebRtcChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/WebRtcSpoofingType"
}
],
"description": "Specifies how the WebRTC will be spoofed. Possible values:\r\n'automatic': Automatically set the webRTC public IP by the IP\r\n'manual': Manually override the webRTC public IP and private IP in the profile\r\n'block': Block the WebRTC functionality\r\n'off': Turn off the spoofing, use the original settings"
},
"extra": {
"required": ["publicIp"],
"allOf": [
{
"$ref": "#/components/schemas/WebRtcSpoofingOptions"
}
],
"description": "When the WebRTC spoofing is set to manual these extra settings will be used as well.",
"nullable": true
}
},
"additionalProperties": false
},
"WebRtcSpoofingOptions": {
"required": ["publicIp"],
"type": "object",
"properties": {
"publicIp": {
"type": "string",
"description": "The WebRTC public IP address of the machine.",
"example": "193.40.239.9"
}
},
"additionalProperties": false,
"description": "When the WebRTC spoofing is set to manual these extra settings will be used as well."
},
"WebRtcSpoofingType": {
"enum": ["automatic", "manual", "block", "off"],
"type": "string",
"description": "Specifies how the WebRTC will be spoofed. Possible values:\r\n'automatic': Automatically set the webRTC public IP by the IP\r\n'manual': Manually override the webRTC public IP and private IP in the profile\r\n'block': Block the WebRTC functionality\r\n'off': Turn off the spoofing, use the original settings"
},
"WebglMeta": {
"required": ["vendor"],
"type": "object",
"properties": {
"vendor": {
"type": "string",
"description": "The UnmaskedVendor field from WebGL context",
"example": "Google Inc. (AMD)"
},
"renderer": {
"type": "string",
"description": "The UnmaskedRenderer field from WebGL context",
"nullable": true,
"example": "ANGLE (AMD, AMD Radeon(TM) RX Vega 11 Graphics Direct3D11 vs_5_0 ps_5_0, D3D11)"
}
},
"additionalProperties": false
},
"WebglMetaChoice": {
"required": ["value"],
"type": "object",
"properties": {
"value": {
"allOf": [
{
"$ref": "#/components/schemas/WebglMetaSpoofingType"
}
],
"description": "Specifies how the WebGL vendor and renderer will be spoofed. Possible values:\r\n'automatic': The vendor and renderer values comes from the fingerprint.\r\n'manual': Manually configure WebGL metadata. For optimal results, choose a video card model similar to your device's to ensure realistic\r\nprofile masking.\r\n'off': Turn off the spoofing, use the original settings"
},
"extra": {
"allOf": [
{
"$ref": "#/components/schemas/WebglMetaSpoofingOptions"
}
],
"description": "When the WebGL Meta spoofing is used, these settings can override the values in the fingerprint.",
"nullable": true
}
},
"additionalProperties": false
},
"WebglMetaSpoofingOptions": {
"type": "object",
"properties": {
"vendor": {
"type": "string",
"description": "Unmasked vendor",
"nullable": true,
"example": "Google Inc."
},
"renderer": {
"type": "string",
"description": "Unmasked renderer",
"nullable": true,
"example": "ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)"
}
},
"additionalProperties": false,
"description": "When the WebGL Meta spoofing is used, these settings can override the values in the fingerprint."
},
"WebglMetaSpoofingType": {
"enum": ["automatic", "manual", "off"],
"type": "string",
"description": "Specifies how the WebGL vendor and renderer will be spoofed. Possible values:\r\n'automatic': The vendor and renderer values comes from the fingerprint.\r\n'manual': Manually configure WebGL metadata. For optimal results, choose a video card model similar to your device's to ensure realistic\r\nprofile masking.\r\n'off': Turn off the spoofing, use the original settings"
},
"WebglSpoofingType": {
"enum": ["noise", "block", "off"],
"type": "string",
"description": "Specifies how the WebGL will be spoofed. Possible values:\r\n'noise': Add some noise to the WebGL generation\r\n'block': Completely block the 3D API\r\n'off': Turn off the spoofing, use the original settings"
}
}
},
"tags": [
{
"name": "Cookie"
},
{
"name": "Fingerprint"
},
{
"name": "Folder"
},
{
"name": "General"
},
{
"name": "Kernel"
},
{
"name": "Profile"
}
]
}
```
---