# Incogniton Documentation — Full Text > Welcome to the Incogniton API documentation. Learn about features, capabilities, and how to get started. > Source: https://docs.incogniton.com --- # Introduction Source: https://docs.incogniton.com/ # Incogniton Developers Welcome to the official developer documentation for the Incogniton Antidetect browser API and SDKs. Designed for a great developer experience, the API and SDKs give you full programmatic control over fingerprinting settings, proxy configurations, cookie management, and browser session, all right from your code. ### What You Can Do: - Create and manage your antidetect browser profiles programmatically - Rotate proxies and configure fingerprint settings - Import, export, and delete cookies - Launch stealth browsers via Puppeteer, Playwright or Selenium - Run browser automation scripts seamlessly, using our SDKs ### Getting Started: Get up and running fast with setup instructions and make your first API call in minutes. Install and use our TypeScript and Python SDKs for streamlined development. Follow step-by-step guides to solve common integration and automation tasks. Explore every available endpoint with request/response formats and examples. --- # Introduction Source: https://docs.incogniton.com/getting-started/introduction # Incogniton Developers Welcome to the official developer documentation for the Incogniton Antidetect browser API and SDKs. Designed for a great developer experience, the API and SDKs give you full programmatic control over fingerprinting settings, proxy configurations, cookie management, and browser sessions — all right from your code. ### What You Can Do: - Create and manage your antidetect browser profiles programmatically - Rotate proxies and configure fingerprint settings - Import, export, and delete cookies - Launch stealth browsers via Puppeteer, Playwright or Selenium - Run browser automation scripts seamlessly, using our SDKs - Control everything from your terminal with the [Incogniton CLI](/cli) ### Getting Started: Get up and running fast with setup instructions and make your first API call in minutes. Install and use our TypeScript and Python SDKs for streamlined development. Drive profiles, cookies, and automation straight from your terminal — no code required. Follow step-by-step guides to solve common integration and automation tasks. Explore every available endpoint with request/response formats and examples. --- # Quickstart Source: https://docs.incogniton.com/getting-started/quickstart # Quickstart This guide will cover the essential steps to get you started with the Incogniton API, including installing the SDK, launching a browser profile, and making your first API calls. ## Requirements Before you begin, let’s make sure you have everything you need: - An Incogniton account — [sign up here](https://incogniton.com/pricing/) if you don't have one - The [Incogniton desktop app](https://incogniton.com/download-incogniton/) downloaded, installed, and running on your computer - At least one [browser profile created](https://www.youtube.com/watch?v=9gsKirc45L0) within the Incogniton app - A working knowledge of either TypeScript/JavaScript or Python The SDK and REST API communicate locally with the running Incogniton desktop application over CDP or WebDriver. All commands are executed against profiles stored in the app, and no network calls leave your machine unless your automation script explicitly navigates to external pages. No API tokens are required — all API calls are executed locally via the Incogniton app. ## Installation and Usage In this section, we will walk through the steps to install the Incogniton SDK and make your first API calls. You may also use direct HTTP requests to the REST API if you prefer. We provide official SDKs for TypeScript (Node.js) and Python. Choose your preferred language and run the matching install command below: ```bash npm install incogniton ``` ```bash pip install incogniton ``` Launch a browser profile via the SDK or a direct HTTP request, as shown below. This initializes an Incogniton browser instance on your local server with the specified profile. ```javascript import { IncognitonClient } from 'incogniton'; const client = new IncognitonClient(); const profileId = 'your-profile-id'; await client.profile.launch(profileId); ```` ```python import asyncio from incogniton import IncognitonClient async def main(): client = IncognitonClient() profile_id = 'your-profile-id' await client.profile.launch(profile_id) asyncio.run(main()) ```` ```bash curl http://localhost:35000/profile/launch/{profile_id} ``` Use the Incogniton Browser Automation SDK with Playwright to perform a quick automation task: launch a profile, navigate to a page, and take a screenshot. ```javascript import { IncognitonBrowser } from 'incogniton'; const profileId = 'your-profile-id'; // Create a browser automation instance const browser = new IncognitonBrowser({ headless: true }); // Launch a Playwright browser instance const playwrightBrowser = await browser.startPlaywright(); // Open a new page and navigate const page = await playwrightBrowser.newPage(); await page.goto('https://example.com'); // Take a screenshot await page.screenshot({ path: 'example.png' }); // Close the browser when done await browser.close(playwrightBrowser); ``` ```python import asyncio from incogniton import IncognitonClient, IncognitonBrowser async def main(): # Create a browser automation instance bound to a profile browser = IncognitonBrowser(profile_id="your-profile-id", headless=True) # Launch a Playwright browser playwright_browser = await browser.start_playwright() page = await playwright_browser.new_page() await page.goto("https://example.com") # Take a screenshot await page.screenshot(path="example.png") # Close the browser when done await browser.close(playwright_browser) asyncio.run(main()) ``` Browser automation tasks and endpoints in the IncognitonBrowser module are SDK-exclusive and cannot be called directly via the REST API. You now have a running browser instance and can proceed to advanced automation tasks. ## Next Steps Follow step-by-step tutorials for automating your Incogniton profiles with Puppeteer, Playwright, and Selenium. See every available API endpoint with usage examples and detailed parameters. --- Need help? Join our [community](https://t.me/incognitonOfficial) or [contact support](https://incogniton.com/contact/). --- --- # API Reference Source: https://docs.incogniton.com/apis --- # API Reference The Incogniton API Reference provides a complete set of endpoints for managing browser profiles, cookies, and automation workflows. It details the technical specifications and methods for programmatically creating, configuring, launching, and deleting profiles, ensuring precise control over the Incogniton browser for integration with your development environment. --- ## Profile Operations The Profile Operations endpoints allow you to manage browser profiles on the Incogniton platform. Create, retrieve, launch, and delete profiles to efficiently handle configuration and automation workflows. --- ## Add a profile Creates a new browser profile using the provided configuration details, including general profile information, proxy settings, timezone, WebRTC, navigator settings, and other options. The profile document can be sent either wrapped in a top-level `profileData` key or as the bare document at the top level — both shapes are accepted. - **profileData** (object) - **general_profile_information** (object, required) - **profile_name** (string) A human-readable name for the profile (e.g., the browser or user profile name displayed in the UI). - **profile_notes** (string) Optional notes or comments about the profile's purpose or usage. - **profile_group** (string) Category or group identifier used to organize profiles (e.g., work, personal, testing). - **profile_last_edited** (string) The ISO 8601 timestamp when the profile was last modified. - **simulated_operating_system** (string) The operating system to emulate for the profile (e.g., Windows, macOS, Linux). - **profile_browser_version** (string) The browser version or engine version that the profile simulates (ensures consistent fingerprinting). Encapsulates core profile details including the display name, notes, group, last edited timestamp, simulated operating system, and browser version. - **unblocked_free_proxy_settings** (object) - **unblocked_free_proxy_enabled** (boolean) Enable the built-in Unblocked free proxy network for this profile. When enabled, the browser automatically routes traffic through the chosen proxy. - **unblocked_free_proxy_country** (string) Country to request a free proxy from (lowercase shortname). Options include: `us`, `hk`, `br`, `nl`, `au`, `uk`, `de`, `in`, `ua`. Manages the selection and configuration of the built-in Unblocked free proxy for this profile, including whether it is enabled and which country to route traffic through. - **proxy** (object) - **connection_type** (string) Specifies the type of proxy connection (e.g., `HTTP` or `SOCKS5`). - **proxy_url** (string) The URL or IP address (with port) of the proxy server. - **proxy_username** (string) Username required for proxy authentication, if applicable. - **proxy_password** (string) Password required for proxy authentication, if applicable. - **proxy_rotating** (number) Indicates whether proxy rotation is enabled (or the rotation interval/count); typically '1' for enabled or a numeric value representing rotation settings. - **proxy_provider** (string) Identifier or name of the proxy provider service. Defines the proxy connection settings including type, URL, authentication credentials, rotation options, and provider information. - **timezone** (object) - **fill_timezone_based_on_ip** (boolean) If `true`, the system will automatically detect and fill the timezone based on the IP address. - **timezone_name** (string) The standard name of the timezone (e.g., 'America/New_York'). - **timezone_offset** (number) The offset from UTC (in minutes) for the specified timezone. Specifies the timezone configuration for a profile, supporting both automatic IP-based detection and manual timezone settings. - **webRTC** (object) - **set_external_ip** (boolean) If true, sets a custom external IP address to be used by WebRTC to mitigate IP leakage. - **behavior** (string) Specifies the WebRTC behavior mode (e.g., 'default', 'stealth') to control how IPs are handled. - **public_ip** (string) The public IP address to be advertised via WebRTC, if overriding the actual public IP. - **local_ip** (string) The local (LAN) IP address to be used in WebRTC sessions. Configures WebRTC settings to manage IP exposure, including options to set custom external and local IP addresses and specify the behavior mode. - **navigator** (object) - **user_agent** (string) The User-Agent string that the browser will report; critical for fingerprint consistency. - **screen_resolution** (string) Screen resolution in a 'WIDTHxHEIGHT' format to simulate a specific display size. - **navigator_useragent_match_chrome_core** (boolean) If true, forces the navigator's User-Agent string to match the Chrome core version for uniformity. - **languages** (string) A comma-separated list of language codes that the browser should report (e.g., 'en-US,fr-FR'). - **navigator_languageIPToggle** (number) Numeric flag to determine if the browser language should be automatically toggled based on IP-derived locale (typically 0 or 1). - **platform** (string) Specifies the platform reported by the browser (e.g., 'Win32', 'MacIntel'). - **do_not_track** (boolean) Indicates whether the browser should enable the Do Not Track setting. - **hardware_concurrency** (number) The number of logical processor cores to simulate for performance and fingerprinting. - **navigator_useragent_always_latest** (boolean) If enabled, the system always updates the User-Agent string to the latest available version. Contains browser navigator settings for fingerprint consistency, including the User-Agent, screen resolution, language settings, and platform details. - **other** (object) - **active_session_lock** (boolean) Prevents changes to the profile while an active session is running. - **other_ShowProfileName** (boolean) If true, the profile name is displayed in areas where it might otherwise be hidden. - **custom_browser_args_enabled** (boolean) Enables the use of custom command-line arguments for the browser instance. - **custom_browser_args_string** (string) A string of custom browser arguments to be applied at startup. - **browser_language_lock** (boolean) Locks the browser language to a custom setting, preventing auto-detection. - **custom_browser_language** (string) The custom language setting for the browser (e.g., 'en-US'). Provides additional, miscellaneous configuration options to fine-tune profile behavior, including session locking, display settings, custom browser arguments, and language preferences. An object containing all configuration settings required to create or update a browser profile, including general information, proxy, timezone, WebRTC, navigator, and additional custom options. ```bash curl -X POST http://localhost:35000/profile/add \ -H "Content-Type: application/json" -d '{ "profileData": { "Timezone": { "fill_timezone_based_on_ip": false, "timezone_offset": "+01:00", "timezone_name": "Europe/Berlin" }, "general_profile_information": { "profile_browser_version": "120", "simulated_operating_system": "Linux", "profile_name": "Automation Bot", "browser_id": "a1b2c3d4-e5f6-7890-ab12-cd34ef56gh78", "profile_notes": "Automated task profile", "profile_group": "Automation", "profile_last_edited": "2025-03-10" }, "WebRTC": { "local_ip": "10.10.10.100", "public_ip": "", "behavior": "Masked", "set_external_ip": true }, "Other": { "browser_allowRealMediaDevices": false, "active_session_lock": false, "other_ShowProfileName": false, "custom_browser_args_enabled": false, "browser_language_lock": false, "custom_browser_language": "fr-FR", "custom_browser_args_string": "" } } }' ``` ```bash incogniton-cli profile-add --data @profile.json ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.add({ "profile_name": "New Profile", "platform": "windows", "userAgent": "Mozilla/5.0" }); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.add({ "profile_name": "New Profile", "platform": "windows", "userAgent": "Mozilla/5.0" }) print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "profile_browser_id": "e06d24a7-ccd2-456e-86d4-1e8a572bfae5", "status": "ok" } ``` --- ## Launch profile This endpoint initiates the launch of a specific browser profile. It starts the profile session using the configuration specified in your settings. - **profile_id** (string, required) The unique identifier of the profile to launch. ```bash curl -G http://localhost:35000/profile/launch/{profile_id} \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli profile-launch --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.launch("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.launch("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile launched", "status": "ok" } ``` --- ## Launch profile force Local sync Launches a browser profile and forces synchronization using the latest local backup. It helps solve out-of-sync or related browser profile issues. - **profile_id** (string, required) The browser profile ID. ```bash curl -G http://localhost:35000/profile/launch/{profile_id}/force/local \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-launch-force-local --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.launchForceLocal("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.launch_force_local("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile launched", "status": "ok" } ``` --- ## Launch profile force Cloud sync Launches a browser profile and forces synchronization using the latest cloud backup. It helps solve out-of-sync or similar browser profile issues. - **profile_id** (string, required) The browser profile ID. ```bash curl -G http://localhost:35000/profile/launch/{profile_id}/force/cloud \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-launch-force-cloud --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.launchForceCloud("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.launch_force_cloud("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile launched", "status": "ok" } ``` --- ## Update a profile Updates a browser profile with the specified settings. The document can be sent either wrapped in a top-level `profileData` key or as the bare document — both shapes are accepted. Either way it must include a top-level `profile_browser_id` identifying the profile to update. - **profile_browser_id** (string) The unique identifier of the browser profile. - **general_profile_information** (object) - **profile_name** (string) A human-readable name for the profile (e.g., the browser or user profile name displayed in the UI). - **profile_notes** (string) Optional notes or comments about the profile's purpose or usage. - **profile_group** (string) Category or group identifier used to organize profiles (e.g., work, personal, testing). - **profile_last_edited** (string) The ISO 8601 timestamp when the profile was last modified. - **simulated_operating_system** (string) The operating system to emulate for the profile (e.g., Windows, macOS, Linux). - **profile_browser_version** (string) The browser version or engine version that the profile simulates (ensures consistent fingerprinting). Encapsulates core profile details including the display name, notes, group, last edited timestamp, simulated operating system, and browser version. - **unblocked_free_proxy_country** (object) - **unblocked_free_proxy_enabled** (boolean) Enable the built-in Unblocked free proxy network for this profile. When enabled, the browser automatically routes traffic through the chosen proxy. - **unblocked_free_proxy_country** (string) Country to request a free proxy from (lowercase shortname). Options include: `us`, `hk`, `br`, `nl`, `au`, `uk`, `de`, `in`, `ua`. Manages the selection and configuration of the built-in Unblocked free proxy for this profile, including whether it is enabled and which country to route traffic through. - **proxy** (object) - **connection_type** (string) Specifies the type of proxy connection (e.g., `HTTP` or `SOCKS5`). - **proxy_url** (string) The URL or IP address (with port) of the proxy server. - **proxy_username** (string) Username required for proxy authentication, if applicable. - **proxy_password** (string) Password required for proxy authentication, if applicable. - **proxy_rotating** (number) Indicates whether proxy rotation is enabled (or the rotation interval/count); typically '1' for enabled or a numeric value representing rotation settings. - **proxy_provider** (string) Identifier or name of the proxy provider service. Defines the proxy connection settings including type, URL, authentication credentials, rotation options, and provider information. - **timezone** (object) - **fill_timezone_based_on_ip** (boolean) If `true`, the system will automatically detect and fill the timezone based on the IP address. - **timezone_name** (string) The standard name of the timezone (e.g., 'America/New_York'). - **timezone_offset** (number) The offset from UTC (in minutes) for the specified timezone. Specifies the timezone configuration for a profile, supporting both automatic IP-based detection and manual timezone settings. - **webRTC** (object) - **set_external_ip** (boolean) If true, sets a custom external IP address to be used by WebRTC to mitigate IP leakage. - **behavior** (string) Specifies the WebRTC behavior mode (e.g., 'default', 'stealth') to control how IPs are handled. - **public_ip** (string) The public IP address to be advertised via WebRTC, if overriding the actual public IP. - **local_ip** (string) The local (LAN) IP address to be used in WebRTC sessions. Configures WebRTC settings to manage IP exposure, including options to set custom external and local IP addresses and specify the behavior mode. - **navigator** (object) - **user_agent** (string) The User-Agent string that the browser will report; critical for fingerprint consistency. - **screen_resolution** (string) Screen resolution in a 'WIDTHxHEIGHT' format to simulate a specific display size. - **navigator_useragent_match_chrome_core** (boolean) If true, forces the navigator's User-Agent string to match the Chrome core version for uniformity. - **languages** (string) A comma-separated list of language codes that the browser should report (e.g., 'en-US,fr-FR'). - **navigator_languageIPToggle** (number) Numeric flag to determine if the browser language should be automatically toggled based on IP-derived locale (typically 0 or 1). - **platform** (string) Specifies the platform reported by the browser (e.g., 'Win32', 'MacIntel'). - **do_not_track** (boolean) Indicates whether the browser should enable the Do Not Track setting. - **hardware_concurrency** (number) The number of logical processor cores to simulate for performance and fingerprinting. - **navigator_useragent_always_latest** (boolean) If enabled, the system always updates the User-Agent string to the latest available version. Contains browser navigator settings for fingerprint consistency, including the User-Agent, screen resolution, language settings, and platform details. - **other** (object) - **active_session_lock** (boolean) Prevents changes to the profile while an active session is running. - **other_ShowProfileName** (boolean) If true, the profile name is displayed in areas where it might otherwise be hidden. - **custom_browser_args_enabled** (boolean) Enables the use of custom command-line arguments for the browser instance. - **custom_browser_args_string** (string) A string of custom browser arguments to be applied at startup. - **browser_language_lock** (boolean) Locks the browser language to a custom setting, preventing auto-detection. - **custom_browser_language** (string) The custom language setting for the browser (e.g., 'en-US'). Provides additional, miscellaneous configuration options to fine-tune profile behavior, including session locking, display settings, custom browser arguments, and language preferences. ```bash curl -X POST http://localhost:35000/profile/update \ -H "Content-Type: application/json" -d '{ "profileData": { "profile_browser_id": "e2124f8a-0a05-48e3-b26a-0b5349c779f5", "general_profile_information": { "profile_name": "Example Account", "profile_notes": "", "profile_group": "Unassigned", "profile_last_edited": "", "simulated_operating_system": "Windows", "profile_browser_version": "117" }, "Proxy": { "connection_type": "HTTP proxy", "proxy_url": "123.123.123.123:4444", "proxy_username": "USERNAME", "proxy_password": "PASSWORD", "proxy_rotating": "0" }, "Timezone": { "fill_timezone_based_on_ip": true, "timezone_name": "Africa/Abidjan", "timezone_offset": "0" }, "WebRTC": { "set_external_ip": true, "behavior": "Altered", "public_ip": "", "local_ip": "192.168.0.01" }, "Navigator": { "user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36", "screen_resolution": "1920x1080", "languages": "en_US", "navigator_languageIPToggle": "0", "platform": "Win32", "do_not_track": true, "hardware_concurrency": 6, "navigator_useragent_always_latest": false }, "Other": { "active_session_lock": true, "other_ShowProfileName": true, "custom_browser_args_enabled": false, "custom_browser_args_string": "", "browser_language_lock": false, "custom_browser_language": "" } } }' ``` ```bash incogniton-cli profile-update --data @profile.json ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.update("PROFILE_ID", { "profile_id": "PROFILE_ID", "name": "Updated profile", "platform": "windows", "userAgent": "Mozilla/5.0", "proxy": { "host": "proxy.example.com", "port": 8080, "username": "user", "password": "pass" } }); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.update("PROFILE_ID", { "profile_id": "PROFILE_ID", "name": "Updated profile", "platform": "windows", "userAgent": "Mozilla/5.0", "proxy": { "host": "proxy.example.com", "port": 8080, "username": "user", "password": "pass" } }) print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile updated", "status": "ok" } ``` --- ## List all profiles Retrieve a comprehensive list of all browser profiles associated with your account. ```bash curl -G http://localhost:35000/profile/all ``` ```bash incogniton-cli profile-get-all ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.list(); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.list() print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "profileData": [ { "Timezone": { "fill_timezone_based_on_ip": true, "timezone_offset": "+03:00", "timezone_name": "Africa/Addis_Ababa" }, "general_profile_information": { "profile_browser_version": "129", "simulated_operating_system": "mac", "profile_name": "Profile 1", "profile_group": "Unassigned", "profile_last_edited": "2025-02-04" }, "Geolocation": { "fill_geolocation_based_on_ip": true, "behavior": "Prompt", "location_information": { "latitude": "8.46", "longitude": "39.38", "accuracy": "3212.0" } }, "Navigator": { "navigator_languageIPToggle": true, "hardware_concurrency": "SIXTEEN", "languages": "en_US", "do_not_track": false, "screen_resolution": "1360x768", "navigator_useragent_always_latest": true, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.182 Safari/537.36", "platform": "MacIntel", "navigator_deviceMemory": "8", "navigator_useragent_match_chrome_core": false }, "Media_devices": { "audio_outputs": 2, "video_outputs": 2, "enable_media_masking": true, "audio_inputs": 4 }, "Fonts": { "enable_font_list_masking": true, "enable_unicode_glyps_domrect": false }, "Extensions": { "contains_extensions": false }, "UnblockedFreeProxySettings": { "unblocked_free_proxy_country": "IN", "unblocked_free_proxy_enabled": true }, "Proxy": { "connection_type": "Without proxy", "proxy_rotating": 0, "proxy_provider": "main-ipinfo" }, "CustomDNS": { "customDNS_enabled": true }, "Hardware": { "WebGL": { "WebGL_meta": { "WebGL_meta_behavior": "Mask" }, "WebGL_image": { "WebGL_behavior": "Off" } }, "Canvas": { "Canvas_behavior": "Off" }, "AudioContext": { "Audio_Context_behavior": "Noise" } }, "WebRTC": { "behavior": "Altered", "set_external_ip": true }, "Other": { "browser_allowRealMediaDevices": false, "other_try_to_pass_iphey": false, "active_session_lock": true, "other_ShowProfileName": true, "custom_browser_args_enabled": false, "browser_language_lock": true, "other_doNotShowChromeSettings": false } }, { "Timezone": { "fill_timezone_based_on_ip": true, "timezone_offset": "-05:00", "timezone_name": "America/Indiana/Vincennes" }, "general_profile_information": { "profile_browser_version": "131", "simulated_operating_system": "mac", "profile_name": "Profile 2", "profile_group": "Unassigned", "profile_last_edited": "2025-02-04" }, "Geolocation": { "fill_geolocation_based_on_ip": true, "behavior": "Prompt", "location_information": { "latitude": "41.88", "longitude": "-86.31", "accuracy": "2501.0" } }, "Navigator": { "navigator_languageIPToggle": true, "hardware_concurrency": "SIX", "languages": "en_US", "do_not_track": false, "screen_resolution": "1600x900", "navigator_useragent_always_latest": true, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.139 Safari/537.36", "platform": "MacIntel", "navigator_deviceMemory": "8", "navigator_useragent_match_chrome_core": false }, "Media_devices": { "audio_outputs": 3, "video_outputs": 3, "enable_media_masking": true, "audio_inputs": 3 }, "Fonts": { "enable_font_list_masking": true, "enable_unicode_glyps_domrect": false }, "Extensions": { "contains_extensions": false }, "UnblockedFreeProxySettings": { "unblocked_free_proxy_country": "US", "unblocked_free_proxy_enabled": true }, "Proxy": { "connection_type": "Without proxy", "proxy_rotating": 0, "proxy_provider": "main-ipinfo" }, "CustomDNS": { "customDNS_enabled": false }, "Hardware": { "WebGL": { "WebGL_meta": { "WebGL_meta_behavior": "Mask" }, "WebGL_image": { "WebGL_behavior": "Off" } }, "Canvas": { "Canvas_behavior": "Off" }, "AudioContext": { "Audio_Context_behavior": "Noise" } }, "WebRTC": { "behavior": "Altered", "set_external_ip": true }, "Other": { "browser_allowRealMediaDevices": false, "other_try_to_pass_iphey": false, "active_session_lock": true, "other_ShowProfileName": true, "custom_browser_args_enabled": false, "browser_language_lock": true, "other_doNotShowChromeSettings": false } } ], "status": "ok" } ``` --- ## Get profile information Returns detailed profile data including timezone, general info, geolocation, navigator settings, media devices, fonts, extensions, proxy, customDNS, hardware, WebRTC configuration, and other custom options, with a status indicator. - **profile_id** (string, required) The browser profile ID ```bash curl -G http://localhost:35000/profile/get/{profile_id} \ # Path params: profile_id=profile_id ``` ```bash incogniton-cli profile-get --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.get("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.get("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "profileData": { "Timezone": { "fill_timezone_based_on_ip": "true", "timezone_offset": "-05:00", "timezone_name": "America/Indiana/Vincennes" }, "general_profile_information": { "profile_browser_version": "131", "simulated_operating_system": "mac", "profile_name": "Profile 1", "profile_notes": "", "profile_group": "Unassigned", "profile_last_edited": "2025-02-04" }, "Geolocation": { "fill_geolocation_based_on_ip": "true", "behavior": "Prompt", "location_information": { "latitude": "41.88", "accuracy": "2501.0", "longitude": "-86.31" } }, "Navigator": { "navigator_languageIPToggle": true, "hardware_concurrency": "SIX", "languages": "en_US", "do_not_track": false, "screen_resolution": "1600x900", "navigator_useragent_always_latest": true, "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.139 Safari/537.36", "platform": "MacIntel", "navigator_deviceMemory": "8", "navigator_useragent_match_chrome_core": false }, "Media_devices": { "audio_outputs": 3, "video_outputs": 3, "enable_media_masking": "true", "audio_inputs": 3 }, "Fonts": { "enable_font_list_masking": "true", "enable_unicode_glyps_domrect": "false" }, "Extensions": { "contains_extensions": "false" }, "UnblockedFreeProxySettings": { "unblocked_free_proxy_country": "US", "unblocked_free_proxy_enabled": true }, "Proxy": { "connection_type": "Without proxy", "proxy_rotation_api_url": "", "proxy_rotating": 0, "proxy_provider": "main-ipinfo", "proxy_url": "" }, "CustomDNS": { "customDNS_enabled": "false", "customDNS_details": "" }, "Hardware": { "WebGL": { "WebGL_meta": { "WebGL_meta_behavior": "Mask" }, "WebGL_image": { "WebGL_behavior": "Off" } }, "Canvas": { "Canvas_behavior": "Off" }, "AudioContext": { "Audio_Context_behavior": "Noise" } }, "WebRTC": { "behavior": "Altered", "set_external_ip": true }, "Other": { "browser_allowRealMediaDevices": "false", "other_try_to_pass_iphey": "false", "active_session_lock": "true", "other_ShowProfileName": "true", "custom_browser_args_enabled": "false", "browser_language_lock": "true", "custom_browser_language": "", "custom_browser_args_string": "", "other_doNotShowChromeSettings": "false" } }, "status": "ok" } ``` --- ## Get profile status Returns the current status of a specific profile, which may be `ready`, `launching`, `launched`, `syncing`, `synced`, etc. - **profile_id** (string, required) The unique identifier of the profile for which the status is retrieved. ```bash curl -G http://localhost:35000/profile/status/{profile_id} \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-status --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.getStatus("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.get_status("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "Ready" } ``` --- ## Stop a profile Stops a launched profile - **profile_id** (string, required) The browser profile ID ```bash curl -G http://localhost:35000/profile/stop/{profile_id} \ # Path params: profile_id=profile_id ``` ```bash incogniton-cli profile-stop --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.stop("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.stop("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile stopped", "status": "ok" } ``` --- ## Force stop a profile Forcefully stops a launched profile, terminating all associated processes and connections. - **profile_id** (string, required) The browser profile ID ```bash curl -G http://localhost:35000/profile/force-stop/{profile_id} \ # Path params: profile_id=profile_id ``` ```bash incogniton-cli profile-force-stop --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.forceStop("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.force_stop("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile force stopped", "status": "ok" } ``` --- ## Delete a profile Deletes the profile with the specified ID. - **profile_id** (string, required) The unique identifier of the profile to be deleted. ```bash curl -G http://localhost:35000/profile/delete/{profile_id} \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-delete --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.profile.delete("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.delete("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Profile removed", "status": "ok" } ``` --- ## Clone a profile with custom settings Clones an existing profile, letting you choose which settings to copy (cookies, user agent, advanced settings, other browser data) and optionally set a name and group for the clone. The settings can be sent either as bare top-level fields or wrapped in a top-level `profileCloneData` key — both shapes are accepted. - **profile_browser_id** (string, required) Browser id of the source profile. - **profile_name** (string) Name for the clone. Defaults to the source profile's name. - **target_group** (string) Group for the clone. Defaults to the source profile's group. - **clone_cookies** (boolean) Copy cookies. - **clone_advanced_other_settings** (boolean) Copy advanced/other settings. - **clone_useragent** (boolean) Copy the user agent. - **clone_other_browser_data** (boolean) Copy other browser data. ```bash curl -X POST http://localhost:35000/profile/clone \ -H "Content-Type: application/json" -d '{ "profile_browser_id": "PROFILE_ID" }' ``` ```bash incogniton-cli profile-clone-post --profile_browser_id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.clone("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "profile_browser_id": "" } ``` --- ## Clone a profile using all-true defaults Clones with the same name + group as the source and every clone_* option on. - **profile_id** (string, required) Browser id of the source profile. ```bash curl -G http://localhost:35000/profile/clone/{profile_id} \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli profile-clone-get --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.clone_quick("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "profile_browser_id": "" } ``` --- ## Prepare a launch without starting the browser Runs only the prep stages (validate / proxy / sync / server-args / build-command) and returns the built launch command as 'arg'. For clients that want to spawn Chrome themselves or inspect what the launcher would do. - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/profile/dryLaunch/{profile_id} \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli profile-dry-launch --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.dry_launch("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "message": "Profile launched", "arg": "" } ``` --- ## Dry-launch, forcing the LOCAL copy when out of sync No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/profile/dryLaunch/{profile_id}/force/local \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli profile-dry-launch-force-local --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.dry_launch_force_local("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "arg": "" } ``` --- ## Dry-launch, forcing the CLOUD copy when out of sync No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/profile/dryLaunch/{profile_id}/force/cloud \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli profile-dry-launch-force-cloud --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.profile.dry_launch_force_cloud("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "arg": "" } ``` --- ## Cookie operations The Cookie Operations endpoints let you manage cookie data for Incogniton profiles. Retrieve, add, and delete cookies to maintain session integrity and support seamless authentication. --- ## Add Cookie to profile Adds a cookie to a specified Incogniton profile. Requires the profile's unique ID, base64json format, and Base64-encoded JSON cookie data. - **profile_browser_id** (string, required) The unique identifier of the profile in Incogniton. - **format** (string, required) Specifies the encoding format of the cookie data (case-insensitive). One of `json`, `netscape`, `base64json`, or `base64netscape`. - **cookie** (string, required) The cookie data, provided as a Base64-encoded JSON string. ```bash curl -X POST http://localhost:35000/profile/addCookie ``` ```bash incogniton-cli profile-add-cookie --profile_browser_id --format base64json --cookie ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.cookie.add("PROFILE_ID", ); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.cookie.add("PROFILE_ID", ) print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Cookies imported", "status": "ok" } ``` --- ## Get Cookie from profile Retrieves cookie data associated with a specific profile. The response returns a JSON object containing a cookie array with one or more cookie entries (each with details such as name and value). **Wire quirk:** the array is returned under the key `CookieData ` — note the trailing space — preserved for backward compatibility; parse for that exact key. - **profile_id** (string, required) The unique identifier of the profile whose cookie data is being retrieved. ```bash curl -G http://localhost:35000/profile/cookie/{profile_id} \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-cookie-export --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.cookie.get("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.cookie.get("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "CookieData ": [ { "path": "/", "session": false, "domain": ".example.com", "hostOnly": false, "sameSite": "no_restriction", "name": "SESSION_ID", "httpOnly": true, "secure": true, "value": "generic-session-id", "expirationDate": 1760000000 }, { "path": "/", "session": false, "domain": "auth.example.org", "hostOnly": true, "sameSite": "unspecified", "name": "user_token", "httpOnly": false, "secure": true, "value": "generic-user-token", "expirationDate": 1780000000 }, { "path": "/", "session": false, "domain": "auth.example.org", "hostOnly": true, "sameSite": "unspecified", "name": "device_id", "httpOnly": false, "secure": true, "value": "generic-device-id", "expirationDate": 1780000000 }, { "path": "/", "session": false, "domain": ".generic-site.net", "hostOnly": false, "sameSite": "no_restriction", "name": "auth_token", "httpOnly": false, "secure": true, "value": "generic-auth-token-1", "expirationDate": 1755000000 }, { "path": "/", "session": false, "domain": ".generic-site.eu", "hostOnly": false, "sameSite": "no_restriction", "name": "auth_token", "httpOnly": false, "secure": true, "value": "generic-auth-token-2", "expirationDate": 1755000000 }, { "path": "/", "session": false, "domain": "www.generic-site.net", "hostOnly": true, "sameSite": "unspecified", "name": "session_key", "httpOnly": false, "secure": false, "value": "generic-session-key", "expirationDate": 1765000000 }, { "path": "/", "session": false, "domain": ".www.generic-site.net", "hostOnly": false, "sameSite": "unspecified", "name": "cache_data", "httpOnly": false, "secure": true, "value": "{\"expire\":1760000000,\"items\":[\"item1\",\"item2\"]}", "expirationDate": 1760000000 }, { "path": "/", "session": false, "domain": ".www.generic-site.net", "hostOnly": false, "sameSite": "unspecified", "name": "theme", "httpOnly": false, "secure": true, "value": "light", "expirationDate": 1770000000 }, { "path": "/", "session": false, "domain": ".www.generic-site.net", "hostOnly": false, "sameSite": "unspecified", "name": "theme_source", "httpOnly": false, "secure": true, "value": "manual", "expirationDate": 1770000000 }, { "path": "/", "session": false, "domain": ".generic-site.net", "hostOnly": false, "sameSite": "unspecified", "name": "chain_token", "httpOnly": true, "secure": true, "value": "generic-chain-token", "expirationDate": 1760000000 }, { "path": "/", "session": false, "domain": ".generic-site.net", "hostOnly": false, "sameSite": "lax", "name": "csrf_token", "httpOnly": true, "secure": true, "value": "generic-csrf-token", "expirationDate": 0 }, { "path": "/", "session": false, "domain": ".generic-site.net", "hostOnly": false, "sameSite": "no_restriction", "name": "tracking_id", "httpOnly": true, "secure": true, "value": "generic-tracking-id", "expirationDate": 1780000000 } ], "message": "Successfully exported cookies", "status": "ok" } ``` --- ## Delete cookies from profile Remove all stored cookies associated with the specified profile, ensuring a clean browsing session. - **profile_id** (string, required) The unique identifier of the profile whose cookies will be deleted. ```bash curl -G http://localhost:35000/profile/deleteCookie/{profile_id} \ # Path params: profile_id={profile_id} ``` ```bash incogniton-cli profile-cookie-delete --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.cookie.delete("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.cookie.delete("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "message": "Cookies successfully deleted", "status": "ok" } ``` --- ## Automation Operations The Automation Operations endpoints enable automated browser sessions using Incogniton profiles. Launch sessions via `Puppeteer` or `Selenium` to streamline and enhance your automation tasks. --- ## Launch Puppeteer Default This endpoint launches an automated Puppeteer browser session using a specific profile. The profile ID is passed as a URL parameter so that the server can retrieve the corresponding browser configuration - **profile_id** (string, required) The unique identifier of the profile to be launched. ```bash curl -G http://localhost:35000/automation/launch/puppeteer/{profile_id} \ # Path params: profile_id=7093ddfd-58d2-4c7a-b7e7-647d85be9c3f ``` ```bash incogniton-cli puppeteer-launch --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.automation.launchPuppeteer("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_puppeteer("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "puppeteerUrl": "http://127.0.0.1:60128", "status": "ok" } ``` --- ## Launch Selenium Default Launches an automated Selenium browser session using a specific profile. The profile ID is provided as a URL parameter so that the server can retrieve the corresponding browser configuration and initiate the session with default Python settings. - **profile_id** (string, required) The unique identifier of the profile to be launched with Selenium. ```bash curl -G http://localhost:35000/automation/launch/python/{profile_id} \ # Path params: profile_id=7093ddfd-58d2-4c7a-b7e7-647d85be9c3f ``` ```bash incogniton-cli selenium-launch --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.automation.launchSelenium("PROFILE_ID"); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_selenium("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "url": "127.0.0.1:9515/7093ddfd-58d2-4c7a-b7e7-647d85be9c3f", "dataDict": "{}", "successes": [], "errors": [], "status": "ok" } ``` --- ## Launch Puppeteer Custom Launches a Puppeteer-controlled browser session using a specified profile. This allows automation of browsing tasks with a customized environment, including custom command-line arguments such as headless mode. - **profileID** (string, required) The unique identifier of the profile to be used for launching the session. - **forceLocal** (boolean) Force the local copy when out of sync. The legacy alias `force` sets the same flag. - **forceCloud** (boolean) Force the cloud copy when out of sync. - **customArgs** (string) Custom command-line arguments for launching the browser, such as enabling headless mode. ```bash curl -X POST http://localhost:35000/automation/launch/puppeteer \ -H "Content-Type: application/json" -d '{ "profileID": "7093ddfd-58d2-4c7a-b7e7-647d85be9c3f", "customArgs": "--headless=new" }' ``` ```bash incogniton-cli puppeteer-launch-post --profileID ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.automation.launchPuppeteerCustom("PROFILE_ID", ); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_puppeteer_custom("PROFILE_ID", ) print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "puppeteerUrl": "http://127.0.0.1:60128", "status": "ok" } ``` --- ## Launch Selenium Custom Launches a Selenium-controlled browser session with custom command-line arguments, allowing modifications like headless mode while preserving the specified profile's browsing environment. - **profile_id** (string, required) The unique identifier of the profile to be used for launching the session. - **customArgs** (string) Custom command-line arguments for launching the browser, such as enabling headless mode. ```bash curl -X POST http://localhost:35000/automation/launch/python/{profile_id}/ \ # Path params: profile_id={profile_id} \ -H "Content-Type: application/json" -d '{ "customArgs": "--headless=new" }' ``` ```bash incogniton-cli selenium-launch-post-id --id ``` ```javascript import { IncognitonClient } from "incogniton"; const client = new IncognitonClient(); const run = async () => { const response = await client.automation.launchSeleniumCustom("PROFILE_ID", ); console.log(response); }; run(); // Don't forget to run "npm install incogniton" ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_selenium_custom("PROFILE_ID", ) print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "url": "127.0.0.1:9515/7093ddfd-58d2-4c7a-b7e7-647d85be9c3f", "dataDict": "{}", "successes": [], "errors": [], "status": "ok" } ``` --- ## Launch for Puppeteer, forcing the LOCAL copy No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/automation/launch/puppeteer/{profile_id}/local \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli puppeteer-launch-local --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_puppeteer_force_local("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "puppeteerUrl": "" } ``` --- ## Launch for Puppeteer, forcing the CLOUD copy No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/automation/launch/puppeteer/{profile_id}/cloud \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli puppeteer-launch-cloud --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_puppeteer_force_cloud("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "puppeteerUrl": "" } ``` --- ## Launch on the Selenium grid, forcing the LOCAL copy No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/automation/launch/python/{profile_id}/local \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli selenium-launch-local --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_selenium_force_local("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "url": "" } ``` --- ## Launch on the Selenium grid, forcing the CLOUD copy No description available - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/automation/launch/python/{profile_id}/cloud \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli selenium-launch-cloud --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_selenium_force_cloud("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "url": "" } ``` --- ## Launch on the Selenium grid with custom args (POST) Note the trailing slash is part of the registered path. Profile id comes from the profileID field. - **profileID** (string, required) The profile's browser id. - **forceLocal** (boolean) Force the local copy when out of sync. The legacy alias 'force' sets the same flag. - **forceCloud** (boolean) Force the cloud copy when out of sync. - **customArgs** (string) Extra args passed to the launch. ```bash curl -X POST http://localhost:35000/automation/launch/python/ \ -H "Content-Type: application/json" -d '{ "profileID": "PROFILE_ID" }' ``` ```bash incogniton-cli selenium-launch-post --profileID ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_selenium_custom_body("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "url": "" } ``` --- ## Run the cookie-collection robot on a profile Forces the cloud copy and uses default settings (top-50 sites, 120s timeout, accept-cookies extension, random crawl order). - **profile_id** (string, required) The profile's browser id. ```bash curl -G http://localhost:35000/automation/cookieRobot/{profile_id} \ # Path params: profile_id=123e4567-e89b-12d3-a456-426614174000 ``` ```bash incogniton-cli cookie-robot --id ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.automation.launch_cookie_robot("PROFILE_ID") print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "message": "Cookie robot launched" } ``` --- ## System Operations The System Operations endpoints let you check and control the Incogniton application itself. --- ## Health probe Checks that the Incogniton app is running and reachable. Returns the plain-text string `OK` — this is the only endpoint that does not return a JSON response. ```bash curl -G http://localhost:35000/alive ``` ```bash incogniton-cli alive ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.system.alive() print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json "OK" ``` --- ## Shut down the Incogniton application Shuts down the Incogniton application. The API responds before the app closes, so the response always reaches the client. ```bash curl -G http://localhost:35000/incogniton/close ``` ```bash incogniton-cli incogniton-close ``` ```javascript // This endpoint is not supported by the Node.js SDK yet. // Use cURL or the Incogniton CLI instead. ``` ```python from incogniton import IncognitonClient import asyncio client = IncognitonClient() async def run(): response = await client.system.close() print(response) asyncio.run(run()) # Don't forget to run "pip install incogniton" ``` ```json { "status": "ok", "message": "Closing" } ``` --- --- # SDKs Overview Source: https://docs.incogniton.com/sdks/overview # Official SDKs — Overview The Incogniton API Software Development Kits (SDKs) let you control browser profiles, manage cookies, and run automation tasks from your own scripts — all by connecting to the locally running Incogniton desktop app. ### Available SDKs: Manage profiles, cookies, and run automation in Node.js. Works with Puppeteer, Playwright, and Selenium. Manage profiles, cookies, and run automation in Python. Async/await friendly, with Playwright and Selenium support. ### How the SDKs Work: Each SDK acts as a client library that abstracts the underlying calls to the desktop app. When you invoke a method, the SDK formats the request, sends it to the Local API, and handles all response parsing internally. See flow diagram below: ```python [Developer Script: Node.js SDK] ──┐ ├──> (SDK Calls: async / await) ──> [SDK Layer: incogniton lib] ──> [Incogniton Desktop App: Local API] ──> (CDP / WebDriver) ──> [Browser Profile Instance via Playwright / Puppeteer / Selenium] [Developer Script: Python SDK] ───┘ ``` In cases where the SDK needs to connect to an automation tool—such as when you use the **Incogniton Browser** module—it connects to the browser through the URL provided by the Incogniton app, using CDP or WebDriver. It then executes the required automation tasks, and returns the results to your script. No API tokens are required — all calls run locally via the Incogniton app. ### Prefer the terminal? If you want to drive Incogniton from a shell or script without writing code, the [Incogniton CLI](/cli) exposes every API endpoint as a terminal command. --- # Node.js SDK Source: https://docs.incogniton.com/sdks/nodejs # Node.js SDK The Node.js SDK lets you manage Incogniton profiles, cookies, and run full browser automation from JavaScript/TypeScript by talking to the locally running Incogniton desktop app. Everything stays on your machine—no remote tokens, no cloud roundtrips. ## Requirements Before installing and using the Node.js SDK, ensure you have the following in place: - Incogniton account — [Sign up here](https://incogniton.com/pricing/) if you don’t already have one. - Incogniton desktop app — [Download](https://incogniton.com/download-incogniton/) the app and ensure it’s open and running on your machine. - At least one browser profile created within the Incogniton app. - Node.js 16+ installed on your machine. - Familiarity with using `async/await` in JavaScript/TypeScript. The SDK requires the Incogniton desktop app to be running locally. API calls will not work if the app is closed. ## Installation To get started with the Node.js SDK, you first need to install it. The installation process is straightforward and supports **npm**, **yarn**, and **pnpm** package managers. ```bash npm install incogniton ``` ```bash yarn add incogniton ``` ```bash pnpm add incogniton ``` ## Incogniton Client Usage Examples The Incogniton Node.js SDK provides a simple, fully async API for managing browser profiles and automating browsers. Below are common usage examples to help you get started quickly. All SDK calls run locally on your machine — No API tokens or extra authentication required. ## API Client usage examples (Incogniton Client) Use the API client for profile lifecycle and cookies. The SDK is fully async—`await` every operation that hits the app. ```ts import { IncognitonClient } from 'incogniton' const client = new IncognitonClient() // Create a profile const created = await client.profile.add({ profileData: { name: 'My Profile', // ...other fields }, }) // List profiles const profiles = await client.profile.list() // Get a specific profile const profileId = 'your_profile_id' const profile = await client.profile.get(profileId) // Launch (starts a local, profile-bound browser) await client.profile.launch(profileId) // Stop when done await client.profile.stop(profileId) // ESM assumes "type": "module" — for CommonJS, wrap "await" in an async function. ``` ## Browser Automation Usage (Incogniton Browser) Attach your preferred automation tool (e.g Playwright) to the running, profile-bound browser via CDP. This example shows Playwright, the Puppeteer variant is below. ```ts import { IncognitonClient, IncognitonBrowser } from 'incogniton' const client = new IncognitonClient() const profileId = 'your-profile-id' // Ensure the profile's browser is running await client.profile.launch(profileId) // Controller bound to that profile const browser = new IncognitonBrowser({ profileId, headless: true, }) // Establish CDP session → Playwright Browser const pwBrowser = await browser.startPlaywright() const page = await pwBrowser.newPage() await page.goto('https://example.com') await page.screenshot({ path: 'example.png' }) // Clean shutdown (frees resources) await browser.close(pwBrowser) // Optionally stop the profile/browser await client.profile.stop(profileId) ```` ## Headless mode When you run automation in headless mode, the browser UI doesn’t open. This reduces resource consumption and speeds up execution, making it ideal for high-volume automation tasks. ```ts import { IncognitonBrowser } from 'incogniton' const browser = new IncognitonBrowser({ profileId: 'your-profile-id', headless: true, // Enables headless mode }) ``` --- ## SDK Reference The SDK is a local-first `async` client. It sends your commands to the Incogniton app’s Local API, which launches profile-bound browsers for automation. The SDK then connects via CDP or WebDriver so you can control pages using automation tools like Playwright, Puppeteer, or Selenium. ```plaintext [Your JS/TS Script] ──(async/await)──> [Incogniton SDK] │ ▼ Local API @ http://localhost:35000 │ CDP / Web Driver bridge (Playwright/Puppeteer/Selenium) ▼ [Profile-Bound Incogniton Browser (Chromium)] ```` All operations are async. Chain actions with await to keep control flow predictable and to surface errors promptly. --- ## `IncognitonClient` — Reference Use Incogniton Client for local API actions: profiles, cookies, and starting automation-ready sessions. ### Configuration: | Option | Purpose | | --------: | :---------------------------------------------------- | | `baseUrl` | Local API address (default `http://localhost:35000`). | | `port` | Convenience override for the local API port. | | `timeout` | Request timeout for client calls (if supported). | **Profile Operations (`client.profile`)** High-level lifecycle and metadata management. | Method | What it does | | :---------------------------------- | :------------------------------------------------ | | `client.profile.list` | List all browser profiles. | | `client.profile.get` | Get a specific profile by ID. | | `client.profile.add` | Create a new profile. | | `client.profile.update` | Update an existing profile. | | `client.profile.switch_proxy` | Update a profile’s proxy settings. | | `client.profile.launch` | Launch the profile locally (starts the browser). | | `client.profile.launch_force_local` | Launch using only local data. | | `client.profile.launch_force_cloud` | Launch with a fresh cloud sync. | | `client.profile.get_status` | Check current profile status/readiness. | | `client.profile.stop` | Stop the running profile/browser. | | `client.profile.force_stop` | Force stop a running profile/browser immediately. | | `client.profile.delete` | Delete a profile. | **Cookie Operations (`client.cookie`)** Manage cookies without opening a browser. | Method | What it does | | :--------------------- | :-------------------------------- | | `client.cookie.get` | Get all cookies for a profile. | | `client.cookie.add` | Add cookies to a profile. | | `client.cookie.delete` | Delete all cookies for a profile. | **Automation Operations (`client.automation`)** Prepare sessions and get connection endpoints. | Method | What it does | | :------------------------------------------ | :-------------------------------------------- | | `client.automation.launch_puppeteer` | Launch for Puppeteer; returns a DevTools URL. | | `client.automation.launch_puppeteer_custom` | Same, with extra Chromium flags. | | `client.automation.launch_selenium` | Launch for Selenium; returns a WebDriver URL. | | `client.automation.launch_selenium_custom` | Same, with custom ChromeOptions/flags. | --- ## `IncognitonBrowser` — Reference Use Incogniton Browser to attach Playwright/Puppeteer/Selenium to a running, profile-bound browser. Prefer reusing a single controller per worker ### Configuration: | Option | Purpose | | --------------: | :---------------------------------------------- | | `profileId` | Which Incogniton profile to launch/attach. | | `headless` | Run without a visible window (default `false`). | | `customArgs` | Extra Chromium flags (e.g. `--no-sandbox`). | | `launchTimeout` | Max time to wait for readiness (ms). | ### Endpoints & Methods: | Method | What it does | | :------------------------- | :----------------------------------------------- | | `browser.start_playwright` | Return a connected Playwright `Browser` (CDP). | | `browser.start_selenium` | Return a connected Selenium `WebDriver`. | | `browser.close` | Close a single Playwright browser instance. | | `browser.close_all` | Close multiple Playwright instances in parallel. | --- ## Troubleshooting & FAQs Yes. You can customize fingerprint settings either in the Incogniton app (edit your profile’s fingerprint settings before launching) or programmatically via the SDK/API. You can set timezone, language, screen resolution, fonts, WebRTC, and more to align with your target environment. See the API Reference at the end of this page for details. Ensure the Incogniton desktop app is running and you’re logged in. • Check the profile isn’t already open — stop it before relaunching. If stuck syncing, try the “force local” launch option. Confirm Incogniton is running on the same machine and that your plan includes API access. Default port is `35000` — verify it hasn’t been changed in settings. Check firewall rules to ensure the port isn’t blocked. Launch a profile via the automation API or SDK, wait until it’s ready, then connect with `puppeteer.connect()` using the provided DevTools URL. • Install `puppeteer-core` instead of full Puppeteer. See the [Scraping with Incogniton guide](/how-to-guides/scraping-with-Incogniton/) for detailed steps. No. Incogniton bundles its own Chromium build. • No ChromeDriver or separate browser install is required. --- ### Next Steps: Step-by-step guides for common automation and integration tasks. Prefer Python? Use the same capabilities with async/await and Playwright/Selenium. --- Need help? Join our [community](https://t.me/incognitonOfficial) or [contact support](https://incogniton.com/contact/). --- --- # Python SDK Source: https://docs.incogniton.com/sdks/python # Python SDK The Python SDK lets you manage Incogniton profiles, cookies, and run full browser automation from Python by talking to the locally running Incogniton desktop app. Everything stays on your machine—no remote tokens, no cloud roundtrips. ## Requirements Before installing and using the Python SDK, ensure you have the following in place: - Incogniton account — [Sign up here](https://incogniton.com/pricing/) if you don’t already have one. - Incogniton desktop app — [Download](https://incogniton.com/download-incogniton/) the app and ensure it’s open and running on your machine. - At least one [browser profile created](https://www.youtube.com/watch?v=9gsKirc45L0) within the Incogniton app. - Python 3.9+ installed on your machine. The SDK requires the Incogniton desktop app to be running locally. API calls will not work if the app is closed. ## Installation To get started with the Python SDK, install it with your preferred tool. We show **pip**, **pipenv**, and **poetry**. ```bash pip install incogniton ``` ```bash poetry add incogniton ``` ```bash pipenv install incogniton ``` ## How to Use the SDK The Incogniton Python SDK provides a simple, fully async API for managing browser profiles and automating browsers. Below are common usage examples to help you get started quickly. All SDK calls run locally on your machine — No API tokens or extra authentication required. ## Incogniton Client Usage Examples Use the API client for profile lifecycle and cookies. The SDK is async—`await` every operation that talks to the app. ### A. Switch Proxies Update a profile’s proxy and relaunch to apply. ```python import asyncio from incogniton import IncognitonClient async def main(): client = IncognitonClient() pid = "your-profile-id" await client.profile.switch_proxy(pid, { "connection_type": "HTTP", "proxy_url": "proxy.example.com:8080", "proxy_username": "user", "proxy_password": "pass" }) await client.profile.stop(pid) await client.profile.launch(pid) if __name__ == "__main__": asyncio.run(main()) ``` ### B. Get Profile Information Read one profile, list all, and check status. ```python import asyncio from incogniton import IncognitonClient async def main(): client = IncognitonClient() pid = "your-profile-id" profile = await client.profile.get(pid) info = profile["profileData"]["general_profile_information"] print(info["profile_name"]) all_profiles = await client.profile.list() print("Total:", len(all_profiles["profileData"])) status = await client.profile.get_status(pid) print("Status:", status["status"]) if __name__ == "__main__": asyncio.run(main()) ``` ## Browser Automation Usage Examples Attach Playwright (or Selenium) to the running, profile-bound browser via CDP/WebDriver. This example shows Playwright. ```python import asyncio from incogniton import IncognitonBrowser async def main(): profile_id = "your-profile-id" browser = IncognitonBrowser(profile_id=profile_id, headless=True) pw_browser = await browser.start_playwright() page = await pw_browser.new_page() await page.goto("https://example.com") await page.screenshot(path="example.png") print("Screenshot saved as example.png") await browser.close(pw_browser) if __name__ == "__main__": asyncio.run(main()) ``` To terminate the running profile immediately after automation completes, use the `force_stop(profile_id)` method. ## Headless mode Headless mode avoids rendering a visible UI, which reduces CPU/GPU usage and speeds up high-volume tasks. To go headless, set the `headless` parameter to `True` when creating the browser instance. See sample below: ```python from incogniton import IncognitonBrowser browser = IncognitonBrowser(profile_id="your-profile-id", headless=True) ``` --- ## SDK Reference The SDK is a local-first `async` client. It sends your commands to the Incogniton app’s Local API, which launches profile-bound browsers for automation. The SDK then connects via CDP or WebDriver so you can control pages using automation tools like Playwright or Selenium. ```plaintext [Your Python Script] ──(async/await)──> [Incogniton SDK] │ ▼ Local API @ http://localhost:35000 │ CDP / WebDriver bridge (Playwright/Selenium) ▼ [Profile-Bound Incogniton Browser (Chromium)] ``` All operations are async. Chain actions with await to keep control flow predictable and to surface errors promptly. --- ## `IncognitonClient` — Reference Use Incogniton Client for local API actions: profiles, cookies, and starting automation-ready sessions. ### Configuration: | Option | Purpose | | ---------: | :---------------------------------------------------- | | `base_url` | Local API address (default `http://localhost:35000`). | | `port` | Convenience override for the local API port. | **System Operations (`client.system`)** App-level health and lifecycle. | Method | What it does | | :---------------------- | :------------------------------------------------------ | | `client.system.alive()` | Health probe; returns `OK` when the app is reachable. | | `client.system.close()` | Shut down the Incogniton desktop app. | **Profile Operations (`client.profile`)** High-level lifecycle and metadata management. | Method | What it does | | :----------------------------------------------- | :----------------------------------------------- | | `client.profile.list()` | List all browser profiles. | | `client.profile.get(profile_id)` | Get a specific profile by ID. | | `client.profile.add(create_request)` | Create a new profile. | | `client.profile.update(profile_id, request)` | Update an existing profile. | | `client.profile.switch_proxy(profile_id, proxy)` | Update a profile’s proxy settings. | | `client.profile.clone(profile_id, ...)` | Clone a profile with custom settings (name, group, what to copy). | | `client.profile.clone_quick(profile_id)` | Clone a profile using all-default settings. | | `client.profile.launch(profile_id)` | Launch the profile locally (starts the browser). | | `client.profile.launch_force_local(profile_id)` | Launch using only local data. | | `client.profile.launch_force_cloud(profile_id)` | Launch with a fresh cloud sync. | | `client.profile.dry_launch(profile_id)` | Build the launch command without starting a browser (returns `arg`). | | `client.profile.dry_launch_force_local(profile_id)` | Dry-launch using only local data. | | `client.profile.dry_launch_force_cloud(profile_id)` | Dry-launch with a fresh cloud sync. | | `client.profile.get_status(profile_id)` | Check current profile status/readiness. | | `client.profile.stop(profile_id)` | Stop the running profile/browser. | | `client.profile.force_stop(profile_id)` | Force-stop a profile stuck in a running state. | | `client.profile.delete(profile_id)` | Delete a profile. | **Cookie Operations (`client.cookie`)** Manage cookies without opening a browser. | Method | What it does | | :--------------------------------------- | :-------------------------------- | | `client.cookie.get(profile_id)` | Get all cookies for a profile. | | `client.cookie.add(profile_id, cookies)` | Add cookies to a profile. | | `client.cookie.delete(profile_id)` | Delete all cookies for a profile. | **Automation Operations (`client.automation`)** Prepare sessions and get connection endpoints. | Method | What it does | | :------------------------------------------------------------------- | :-------------------------------------------- | | `client.automation.launch_puppeteer(profile_id)` | Launch for Puppeteer; returns a DevTools URL. | | `client.automation.launch_puppeteer_force_local(profile_id)` | Same, forcing local data. | | `client.automation.launch_puppeteer_force_cloud(profile_id)` | Same, forcing a fresh cloud sync. | | `client.automation.launch_puppeteer_custom(profile_id, custom_args)` | Same, with extra Chromium flags. | | `client.automation.launch_selenium(profile_id)` | Launch for Selenium; returns a WebDriver URL. | | `client.automation.launch_selenium_force_local(profile_id)` | Same, forcing local data. | | `client.automation.launch_selenium_force_cloud(profile_id)` | Same, forcing a fresh cloud sync. | | `client.automation.launch_selenium_custom(profile_id, custom_args)` | Same, with custom flags (profile id in the URL path). | | `client.automation.launch_selenium_custom_body(profile_id, custom_args=None, force_local=False, force_cloud=False)` | Same, with the profile id sent in the request body. | | `client.automation.launch_cookie_robot(profile_id)` | Run the cookie-collection robot on a profile. | Note: In all method signatures above, profile_id{' '} refers to the `profile_id`, the unique identifier for your Incogniton browser profile. --- ## `IncognitonBrowser` — Reference Use Incogniton Browser to attach Playwright/Selenium to a running, profile-bound browser. Prefer reusing a single controller per worker. ### Configuration: | Option | Purpose | | -------------: | :---------------------------------------------------------------- | | `profile_id` | Which Incogniton profile to launch/attach. | | `headless` | Run without a visible window (default `True`). | | `client` | Optional `IncognitonClient` to reuse (one is created if omitted). | | `launch_delay` | Retained for API stability; no longer used for Playwright launch. | ### Methods: | Method | What it does | | :---------------------------------- | :----------------------------------------------- | | `browser.start_playwright()` | Return a connected Playwright `Browser` (CDP). | | `browser.start_selenium()` | Return a connected Selenium `WebDriver`. | | `browser.close(instance)` | Close a single Playwright/Selenium instance. | | `browser.close_all([instances...])` | Close multiple Playwright instances in parallel. | --- ## Troubleshooting & FAQs Manage fingerprinted, proxy-aware Chromium profiles on your machine and automate them with Playwright or Selenium. Typical uses include scraping, QA tests, and data collection where consistent browser identity and isolation matter. Choose Playwright for modern, async-first automation, rich waiting primitives, and fast parallelism. Choose Selenium if your tooling, infrastructure, or team standards already rely on WebDriver. Both attach to the same profile-bound browser launched by Incogniton. Yes. You can read, add, and delete cookies on a profile directly through the SDK. This is useful for restoring authenticated sessions or wiping state between test runs. Run headless for CI to reduce resource usage and improve stability; switch to headed locally for debugging. In containers or restricted environments, ensure shared memory and sandboxing settings are compatible, and preinstall browsers if your pipeline requires it. Common causes include the Incogniton app being closed, firewall rules blocking localhost, or an overridden port/base URL that doesn’t match your app settings. Confirm the app is running on the same machine and that local networking is permitted. Stop and relaunch the profile, then try forcing a local or cloud launch (See API Reference) if sync is slow. Check status for hints (e.g., launching, running, stopped). Ensuring only one automation session attaches at a time also helps avoid contention. Yes. Launch separate profiles and attach distinct automation sessions, then coordinate them with asyncio. Be mindful of machine resources (CPU/RAM/network) and apply backpressure or concurrency limits to keep runs stable. --- ### Next Steps: Step-by-step guides for common automation and integration tasks. Prefer JavaScript/TypeScript? Use the same capabilities with async/await and Playwright/Puppeteer. --- Need help? Join our [community](https://t.me/incognitonOfficial) or [contact support](https://incogniton.com/contact/). --- --- # How-To Guides Source: https://docs.incogniton.com/how-to-guides/overview # How-To Guides Our How-To Guides walk you through practical tasks with the Incogniton API, from integration and authentication to advanced automation, so you can get started quickly and confidently. ### Read guides: {guides.map((guide) => ( {guide.description} ))} --- --- # Anonymous Web Scraping Overview Source: https://docs.incogniton.com/how-to-guides/anon authorId: 'hay_yusuf', # Anonymous Web Scraping Overview _Content coming soon..._ --- # Beginners Guide to Web Scraping Source: https://docs.incogniton.com/how-to-guides/beginners-guide-to-scraping authorId: 'hay_yusuf', # Beginners guide to Web Scraping (Cheerio, User-Agents) ![scrape anonymously using cheerio and user-agents rotation](https://miro.medium.com/v2/resize:fit:2000/format:webp/1*t357-_nfim7bnEtFpw24ww.gif) Now more than ever, web scraping leads the charge in revolutionary advancements—from training top-of-the-news LLMs like DeepSeekAI and ChatGPT to transforming medical research and improving pricing intelligence. It's fuelling a software market now valued at [over $700M](https://www.researchnester.com/reports/web-scraping-software-market/5041). And of course, given the [_grey area_ nature](https://webscrapeai.com/blogs/blogsContent/is-web-scraping-legal-exploring-the-gray-area) of web scraping, prioritising anonymity as you learn to scrape is a no-brainer. This piece kicks off the **Anonymous Web Scraping series**, where I delve into fundamental web scraping techniques while safeguarding your Personally Identifiable Information (PII), thus avoiding blocks. Subsequent instalments will include: - [**How to scrape dynamically generated sites anonymously**](/how-to-guides/scraping-with-Incogniton). - **How to Export scraped data** (**JSON, CSV, Database)** for further analysis or integration. **In this instalment, you will learn the step-by-step process of scraping static websites anonymously using Javascript, Cheerio and User-Agents header rotation.** ## Prerequisites To follow along easily through the course of this tutorial, ensure you have the following background knowledge and tools ready: - **Javascript basics**. Understanding the basics of Javascript and using `npm` for dependency management. - **HTML and CSS fundamentals**. Familiarity with the `html` DOM and `css` selectors. - **A Code Editor**. You can use any code editor of your choice. I'll be using VS Code on macOS for this tutorial. - **Node.js installed**. Have the Node.js runtime installed. If not, [download and install Node.js](https://nodejs.org/en/download/package-manager) to get started. ## Set up a Node.js Project First, create a new folder called `anonymous-scraper` by running the code below in your terminal: ```bash mkdir anonymous-scraper ``` Navigate into the folder: ```bash cd anonymous-scraper ``` Initialize the Node.js project: ```bash npm init -y ``` This adds a `package.json` file in the root folder that helps track your dependencies, and manage installed libraries. You should also ensure that the `"type": "module"` field is included in your `package.json` file as this tutorial will use ES6 modules. While `Node.js`'s flexibility gets questioned in comparison to `Python` web scraping, its single-threaded model — powered by the multi-threaded V8 engine — makes it an ideal choice for the async-heavy scraping needs. Now let's begin. ## Static-site scraping with Cheerio, Fetch, and User-agent rotation I split the core scraping tutorials into **two tiers**, each offering a distinct **degree of anonymity** and **scraping complexity**. With this approach, I aim to provide you with a thorough understanding of techniques and strategies across both dimensions. This tier explores static site scraping, using the `fetch` API for _http_ requests, [Cheerio](https://cheerio.js.org/) for static HTML parsing, and the [user-agents](https://www.npmjs.com/package/user-agents) library for user-agents rotation. **User agent rotation** involves cycling through a set of **user agent strings** — unique identifiers that specify the client's software and device details — to simulate requests from various browsers and devices. For context, here's a typical user agent string: ```bash Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 ``` The user agent rotation technique masks your real masks your real user agent details, reducing the risk of detection, IP tracking and potential [IP ban](https://incogniton.com/blog/your-ip-has-been-banned-what-it-means-and-how-to-fix-it/) by target websites. And that's why it's a good **starting point** for anonymous scraping. I opted for the built-in `fetch` API (from Node v18) over alternatives like `Axios` and `Superagent` because it is lightweight and doesn't require additional libraries. If you're using an older Node.js version, you may need to [install node-fetch](https://www.npmjs.com/package/node-fetch) to use `fetch()`. That being said, let's write some code. ## Step 1: Create the scraper file and install the necessary dependencies Create a new file named `anon-scraper1.js` and open the file. You can do this by running the following command on your terminal: ```bash touch anon-scraper1.js ``` Next, run the following command to install the `cheerio` and `user-agents` packages: ```bash npm install cheerio user-agents ``` ## Step 2: Fetch the HTML Content of Your Target Website To fetch the HTML of your target website, use the fetch API to send a request to the website, retrieve its HTML, and prepare it for parsing. See code below: ```js const fetchStaticData = async () => { try { // Send GET request to fetch website data const PAGE_URL = 'https://books.toscrape.com/' const response = await fetch(PAGE_URL) // Extract text data from the response const data = await response.text() // Log the extracted data console.log(data) } catch (error) { // Handle errors console.error('Error fetching Data ->', error) } } fetchStaticData() ``` The `fetchStaticData()` async function sends a GET request to the specified `PAGE_URL`, then it retrieves the HTML response as text and logs it to the console. The `try-catch` block handles any error during the process. Use the `node` command to run the script in your terminal: ```bash node anon-scraper1.js ``` The terminal will log the raw HTML content of the target web page, including headings, links, and other elements. Expect many lines of output — that's perfectly normal. Notice the similarity between the returned `html` data and the devtools "elements" tab resource when you visit the page itself. This is because `fetch()` retrieves the raw HTML just as a browser would when you load the page. Next, we'll extract specific elements from the page and put the user-agents rotation technique to test. ## Step 3: Scrape data from a specific HTML DOM element In this section, you will find and extract data from a page element using the Cheerio jquery-like syntax. First, open the webpage in a Chromium-based browser (e.g., Chrome, Edge, etc.), inspect the elements, and identify the CSS selectors as shown in the image below with the `article > h3 > a` and `p.price_color` selectors. Once you have the CSS selectors, modify the `fetchStaticData()` function to include the scraping logic as seen below: ```js // import cheerio and user-agents import * as cheerio from 'cheerio' import UserAgent from 'user-agents' const fetchStaticData = async () => { try { const PAGE_URL = 'https://books.toscrape.com/' // Create random user-agents const userAgent = new UserAgent() const randomUserAgent = userAgent.random().toString() // Send GET request with the random user-agent const response = await fetch(PAGE_URL, { headers: { 'User-Agent': randomUserAgent, }, }) const html = await response.text() // Load the HTML into Cheerio for parsing const $ = cheerio.load(html) const selectors = { name: 'article > h3 > a', price: 'p.price_color' } // Extract last product data const lastProduct = { name: $(selectors.name).last().text(), price: $(selectors.price).last().text(), } console.log('lastProduct -> ', lastProduct) } catch (error) { // Handle errors console.error('Error fetching Data ->', error) } } fetchStaticData() ``` This version utilizes the `user-agents` library to generate a `randomUserAgent` header, masking the request origin. Cheerio then parses the raw HTML into a DOM-like structure to extract the "name" and "price" of the page's last product. Here's the output you should get: ```js lastProduct-> { name: "It's Only the Himalayas", price: "£45.17" }; ``` You've just completed a static webpage element scrape. I recommend rerunning the script multiple times while logging `randomUserAgents` on the console so you observe the variations and peculiarities in the generated user-agents. Now let's do something a little more interesting. ## Scrape multiple DOM elements Scraping multiple elements follows the same logic as using a standard loop — an iteration logic. We'll extract the name and price of all products on the page using the Cheerio `.each()` method to loop through each product element (`.product_pod`) and retrieve the required fields. Here's a snippet to demonstrate: ```js const fetchStaticData = async () => { try { // fetch and parse HTML with cheerio... // Extract all product data from the first page const selectors = { name: 'article > h3 > a', price: 'p.price_color' } const productElement = $('.product_pod') // create a products array const products = [] productElement.each(function () { const name = $(this).find(selectors.name).text() const price = $(this).find(selectors.price).text() products.push({ name, price }) }) console.log('products ->', products) } catch (error) { // Handle errors console.error('Error scraping Data -->', error) } } ``` Notice how I use `this` and not the actual DOM element selector - a common pattern with loop methods to contextually reference the current DOM element within the loop. The logged array should look like this: ```js products -> [ { name: 'A Light in the ...', 'price: '£51.77' }, { name: 'Tipping the Velvet', price: '£53.74' }, { name: 'Soumission', price: '£50.10' }, { name: 'Sharp Objects', price: '£47.82' }, // other products on the page... ] ``` **That's about it!** You've completed a static webpage scrape—mission accomplished, promise fulfilled. I recommend taking it a step further by extracting additional fields, like images and availability, to broaden your understanding even more. **Check out the final source code of this tutorial** [**here**](https://github.com/HAYVENO/anonymous-scraper/blob/main/anon-scraper1.js)**.** ## Limitations of this approach As I stated earlier, while it's a good place to start, **the Cheerio-fetch-user-agents approach is not ideal for professional use** due to a number of reasons, including: - **Static HTML only**. This approach is limited to scraping content in the raw html and cannot handle client-side rendered content or any content that requires javascript execution. - **Low-Level Anonymity**. User-agent rotation offers minimal privacy, leaving devices exposed to tracking via [browser-fingerprinting](https://incogniton.com/blog/browser-fingerprinting-complete-guide/), IP monitoring, or behavioural analysis. **Disclaimer: This guide is for educational use only. Scraping public data is generally accepted, but always ensure you read the website terms and follow legal regulations.** ## Conclusion So far we've explored the basics of scraping anonymously using Fetch, Cheerio, and User-agents rotation. But while this method serves as a great starting point, it would fall short for most modern websites as you have learned with its static content and anonymity limitations. In [the next instalment (Tier-2)](/how-to-guides/scraping-with-Incogniton), we'll dive into a more sophisticated, safe, and professional approach that can handle the complexities of advanced scraping and effectively address these limitations. Be there. --- # Export Scraped Data Source: https://docs.incogniton.com/how-to-guides/export-scraped-data authorId: 'hay_yusuf', # How to Export Your Scraped Data to Json, CSV, or a Database ![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*CIEPEUF6MkLLXcyui-MbBw.png) This guide continues the Anonymous Scraping series and assumes familiarity with core scraping concepts and privacy-preserving techniques introduced earlier. Data is the most valuable resource in the world. But unless you process, and derive valuable insights from it, your scraped data is worthless. But of course, to export scraped data, you first need to scrape some data. So if this is your first contact with the series, you may want to catch up: Learn how to scrape dynamic web content using Incogniton and Puppeteer for privacy and efficiency. In this guide, you will learn how to export data from a NodeJS server. There is a wide array of possible formats, which would include: JSON, XML, CSV, XLSX, or even storing it in databases like MySQL and MongoDB. I’ll focus on JSON, CSV, and database exports, as they cover the predominant use cases and offer a balance of simplicity and versatility. ## Brief Overview Here’s a quick rundown of the formats I’ll be covering, alongside their practical applications: - **JSON (Javascript Object Notation)**: The most widely used data interchange format for web apps and APIs. It’s lightweight, easy to parse, and handles nested data quite well. Ideal for sharing data between servers and clients, or interacting with APIs. - **CSV (Comma-Seperated Values)**: A popular choice for data analysis and reporting. It’s compatible with spreadsheet tools like Excel and Google Sheets, making it a great choice for data like product prices and contact lists where the data fits into a table. - **Databases (MySQL, MongoDB, etc.)**: For storing large evolving datasets with complex relationships. Databases provide efficient data management, scalability, and powerful querying capabilities. Ideal for large-scale automated data collection systems, such as customer review trackers or generative AI (LLM) training platforms. ## Prerequisites A working knowledge of **Javascript** and **Node.js** will do. Familiarity with **Prisma ORM** is a plus as well, but not required. ## Project Setup For the fact that you made it to this piece, chances are you have your data prepped, or maybe you’re just here for the know-how. If it’s the latter, and you’d like to code along, then I got you covered. I’ve put together a [**starter file**](https://github.com/HAYVENO/anonymous-scraper/blob/main/export-starter.js) in the **Anonymous-scraper project** to get you up and running in three simple steps: - Clone the [anonymous-scraper](https://github.com/HAYVENO/anonymous-scraper) repo. - Install the dependencies using `npm install`. - Run the `export-starter.js` script using the `node` command as shown below: ![Getting started with export-starter](https://miro.medium.com/v2/resize:fit:2000/format:webp/0*J4qwNWlUabbUQsrn.gif) On the other hand, if you already have a dataset, simply swap out `fetchStaticData()` with the scraping function that returns your data. In the following sections, I’ll break down the process for exporting data via each of the outlined formats: ## 1. Export as JSON Saving the data to a JSON file will require us to write our array data to a file, using the file system. Luckily, Node.js has the in-built filesystem (`fs`) module to take care of that. We’ll use the `fs.writeFile()` method from the built-in `fs` module. See snippet: ```javascript import fs from 'fs/promises' // Function to save data to JSON const exportToJSON = async (data, filename = 'scraped-data.json') => { try { // Write to JSON file await fs.writeFile(filename, JSON.stringify(data, null, 2), 'utf-8') console.log(`Data exported successfully to ${filename}`) } catch (err) { console.error(err) } } export default exportToJSON // usage example: // await exportToJSON(scrapedData); ``` The `exportToJSON` function leverages the `fs` module to asynchronously write your scraped data array to a `scraped-data.json` file. I recommend setting the third argument of `JSON.stringify` to "2" as shown above — this adds indentation to the output data, making it much easier to read. Typically, the generated JSON file’s content looks like this: ```json [ { "name": "A Light in the ...", "price": "£51.77" }, { "name": "Tipping the Velvet", "price": "£53.74" }, { "name": "Soumission", "price": "£50.10" }, { "name": "Sharp Objects", "price": "£47.82" } // other products... ] ``` From here, you can open the file in Finder/File Explorer for inspection, transfer it to other systems or APIs, or continue working with it directly in your Node.js application. ## 2. Export as CSV Just as with its `json` counterpart, exporting data to CSV also demands that we write a `.csv` file. But before that, we need to transform our JavaScript array into properly structured CSV data — which means handling delimiters, headers, and edge cases. That’s a lot of code. Instead, we will use the [json-2-csv](https://www.npmjs.com/package/json-2-csv) package, which does all the heavy lifting for us. ```javascript import fs from 'fs/promises' import { json2csv } from 'json-2-csv' const exportToCSV = async (data, filePath) => { try { // Convert JSON data to CSV format const csvData = await json2csv(data) // Write the CSV data to a file await fs.writeFile(filePath, csvData) console.log(`Data successfully exported to ${filePath}`) } catch (error) { console.error('Error exporting data to CSV:', error) } //example usage - saves the data to anon-scraped.csv exportToCSV(scrapedData, './anon-scraped.csv') } ``` This function saves your scraped data to a file named `anon-scraped.csv` in the current directory, which you can open and process with any CSV-compatible software, including Excel and Google Sheets. But there’s a caveat: if your data contains varying object keys, that would lead to missing or misaligned values in the exported CSV file. Bear in mind that CSV files rely on a consistent object structure. See example: ```javascript const scrapedData = [ { name: 'Product A', price: '£10' }, { name: 'Product B', cost: '£15' }, { name: 'Product C', price: '£20', category: 'Books' }, ] ``` To solve the problem of inconsistencies with this sort of data, we’ll explicitly state the required headers using the `keys` options. See snippet below: ```javascript // Define the headers const csvOptions = { keys: ['name', 'price', 'category'], // Specify the table headers } const csvData = await json2csv(data, csvOptions) // remainder of the logic... ``` That solves it. The keys in the array serve as the CSV headers irrespective of the data shape. Next, we address the most complex approach of the bunch. ## 3. Export to a Database Compared to previous methods, storing your data in a database requires a couple more steps. But to keep it simple, I’ll use the [Prisma](https://www.prisma.io/)-MySQL combination: easy to set up, gets you started in just three steps, and best of all, spares you the pain of writing raw SQL. ### Step 1: Install Prisma Install Prisma and the Prisma-Client by running the following command on your terminal: ```bash npm install prisma @prisma/client ``` ### Step 2: Configure Prisma with SQL You’ll need to get your SQL connection URL/string. If you are using a cloud database, such as PlanetScale or AWS RDS, refer to their dashboard for the correct connection string. The URL format typically looks like this: ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE_NAME ``` Store your connection string/database URL as an `env` variable file as it is sensitive data. ``` DATABASE_URL=mysql://USER:PASSWORD@HOST:PORT/DATABASE_NAME ``` Ensure the SQL database server is running, and the credentials provided in the `.env` file are correct. Incorrect credentials or a missing database may result in connection errors. ### Step 3: Define the Database schema Prisma operates with a schema file `prisma/schema.prisma` that defines your data structure. Modify it to include a model for storing scraped data: ```prisma datasource db { provider = "mysql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model ScrapedData { id Int @id @default(autoincrement()) name String price String? createdAt DateTime @default(now()) } ``` Next, apply these schema changes to your database, running the migration command: ``` npx prisma migrate dev --name init ``` {' '} If you face migration related errors, check that Prisma is properly initialized by running `npx prisma generate` ### Step 4: Insert Data into the Database Once your database is set up, you can use Prisma Client in your Node.js application to insert scraped data. First, import the client: ``` const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient(); ``` Then, insert a record: ```js async function run() { await prisma.scrapedData.create({ data: { name: 'Sample Item', price: '$20.99', }, }) console.log('Data inserted successfully') // Optionally, query and log all records const data = await prisma.scrapedData.findMany() console.log('Stored data:', data) } run() .catch((e) => console.error(e)) .finally(() => prisma.$disconnect()) ``` This [**singleton approach**](https://www.hayven.dev/blog/how-to-setup-redis-using-singleton-pattern) ensures efficient database communication throughout your application. You not only optimize resource usage but also simplify connection management — paving the way for scalable and maintainable code. That brings us to the end of the series — congrats on reaching the very end!🎉 ## Conclusion At the end of the day, data is only as valuable as what you do with it. Whether it’s converting it to JSON for lightweight storage, streaming it to CSV for analysis, or pushing it directly into a Database for real-time application, how you store and structure your data determines its value. Now you know how to do just that. But knowing is only half the battle, implementation is where the real value lies. So go ahead — leverage public data responsibly, respect legal and ethical boundaries, and drive innovations. --- --- # Scraping with Incogniton Source: https://docs.incogniton.com/how-to-guides/scraping-with-Incogniton title: 'Connect Puppeteer to Incogniton Manually for Web Scraping', description: 'Learn how to scrape dynamically loaded websites while maintaining privacy and security using Incogniton and Puppeteer.', image: 'https://miro.medium.com/v2/resize:fit:1100/format:webp/1*RmgqYqrqcQt-rQerz-kQjA.gif', slug: 'scraping-with-incogniton', authorId: 'hay_yusuf', # How to Connect Puppeteer to Incogniton Manually for Web Scraping ![scraping static sites](https://miro.medium.com/v2/resize:fit:1100/format:webp/1*RmgqYqrqcQt-rQerz-kQjA.gif) Puppeteer excels at automating browser interactions, while Incogniton enhances your privacy with robust anti-fingerprinting and [Web Unblocker](https://incogniton.com/blog/unblock-the-web-using-the-incogniton-unblocked-browser-for-unrestricted-access/) technologies. Together, they help you scrape efficiently and securely without compromising on anonymity. This guide covers manual Puppeteer connection. For a more seamless integration, we recommend you use our SDKs. See guides [here](/sdks/overview). This guide takes you through the step-by-step approach to professional web scraping using the Incogniton API with Puppeteer in a Node.js project. ## Prerequisites To be able to follow along smoothly, ensure you have the following in place: 1. A Node.js environment set up on your computer. 2. Basic knowledge of JavaScript. 3. Familiarity with using the terminal or command line. ## Dynamic Content: A Quick Overview Dynamic content refers to webpage content that is not present in the initial server-rendered HTML, but is instead loaded or modified using client-side javascript logic. Simply put, content that your computer runs in your browser using Javascript. Examples include lazy-loaded images, infinite scrolling, and content rendered by Single-page applications (SPAs). One way to verify that a page is dynamically rendered is to disable Javascript in your browser, using Chrome DevTools. See the steps below: - Open Chrome DevTools (`F12`). - Press `Ctrl + Shift + P` or `Cmd + Shift + P` on Mac to open the Command Menu. - Enter "Disable JavaScript" in the search bar and select the corresponding option. - Reload the page and observe the difference. JavaScript-generated content will not be populated. To return to the default state, close the DevTools panel and reload the page once again. Now, onto the tools powering our scraping workflow. Here's an brief overview of Puppeteer and Incogniton: ### Puppeteer Puppeteer is a JavaScript library that automates Chrome browsers via the [Chrome DevTools Protocol (CDP)](https://chromedevtools.github.io/devtools-protocol/), enabling programmatic executions and user interaction simulations such as clicking or typing. ### Incogniton Browser Incogniton is an [anti-detect browser](https://incogniton.com) with built-in Puppeteer integration, providing anonymity for web scraping and other automation tasks. The Incogniton-Puppeteer integration allows you to launch automated browser sessions within fully isolated profiles, each with a unique [browser fingerprint](https://incogniton.com/blog/browser-fingerprinting-complete-guide/), enabling both headless automation and advanced anti-detection capabilities. ## How to Scrape Dynamic Content: Step-by-Step The following steps outline the process to manually set up and run a javascript-rendered content scraping workflow with Incogniton and Puppeteer: **Note**: Some Incogniton API features are only available within the premium packages. Kindly check the [plans](https://incogniton.com/pricing/) to see what features are included in each package. ## Install and Set Up Incogniton The first step is to install the Incogniton app and create an account. If you already have an Incogniton account, you can skip this step. Otherwise, follow the instructions below: 1. Visit the [Incogniton download page](https://incogniton.com/download-incogniton/). Select the version for your device (Windows or macOS) and download the app. 2. Install the app on your computer. While it's installing, navigate to the website, [choose a plan](https://incogniton.com/pricing/), and create an account. 3. Upon installation, sign in with your credentials. 4. Navigate to profile management and create a [new profile](https://www.youtube.com/watch?v=EUhUlw9gHYs). 5. [Set up your proxy](https://www.youtube.com/watch?v=uTZzl6ThfPc) for IP rotation; Incogniton provides a suite of [proxy deals](https://incogniton.com/proxies/). 6. Complete the profile creation process and get the browser profile ID. Keep the Incogniton Desktop app open and ensure the **profile status** shows `Ready` and not `Launching` or `Syncing` before you run your scripts. ## Connecting Puppeteer to the Incogniton API Create a file named `anon-scraper.js` in your project folder. Then, install the `puppeteer-core` library: ```bash npm install puppeteer-core ``` **Puppeteer-core** instead of **Puppeteer** because the former doesn’t bundle Chromium, making it the ideal choice when you're connecting to an existing browser like Incogniton. Next, use the `puppeteer.connect()` function to connect to the already-running Incogniton browser via the provided DevTools URL returned by the [Launch Puppeteer endpoint](https://api-docs.incogniton.com/apis#launch-puppeteer-custom), allowing Puppeteer to take control of the session. See a demonstration below: ```javascript import puppeteer from 'puppeteer-core' // Function to introduce a delay const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) // Non-headless launch const startIncogniton = async ({ profileId }) => { try { const launchUrl = `http://localhost:35000/automation/launch/puppeteer` const requestBody = { profileID: profileId, } // Make a POST request with body data const response = await fetch(launchUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestBody), }) const data = await response.json() const { puppeteerUrl } = data // Wait for the browser to launch console.log('The Incogniton browser is launching...') await delay(30000) // await initial boot process // Connect Puppeteer to the launched browser const browser = await puppeteer.connect({ browserURL: puppeteerUrl, acceptInsecureCerts: true, }) return browser } catch (error) { console.error('Error starting Incogniton session ->', error) throw error } } ``` For headless mode—better suited for large-scale scraping, modify the request body to include the `customArgs` parameter as shown below: ```javascript // Headless launch const startIncogniton = async ({ profileId }) => { try { const launchUrl = `http://localhost:35000/automation/launch/puppeteer`; const requestBody = { profileID: profileId, customArgs: '--headless=new', // use headless mode }; // Rest of the function remains the same... } }; ``` The example uses port 35000, which is Incogniton’s default. If you’re using a different port, update the `launchUrl` accordingly. To verify that your anti-detect browser instance is well-configured and masking your identity as intended, you should run a fingerprint test. Below is an example using the [IPHey test](https://iphey.com/), which reveals details about your IP address and browser fingerprint. ```javascript const incognitonProfileId = 'YOUR_INCOGNITON_PROFILE_ID' const ipheyTest = async (browser) => { try { const page = await browser.newPage() // Navigate to the IPHey website and wait till zero network requests await page.goto('https://iphey.com/', { waitUntil: 'networkidle0' }) // Check for 'trustworthy status' in the DOM const ipResult = await page.$eval( '.trustworthy-status:not(.hide)', (elt) => (elt ? elt.innerText.trim() : ''), ) console.log('IP Result ->', ipResult) // expected output: 'Trustworthy' await page.close() } catch (error) { console.error('Error during IPHEY test ->', error) } finally { await browser.close() } } // Execute iphey test const testIncognitonProfile = async () => { const browser = await startIncogniton({ profileId: incognitonProfileId }) await ipheyTest(browser) } testIncognitonProfile() ``` All things being equal, the `ipheyTest()` function should return `'Trustworthy'`, indicating that your fingerprint appears clean and is not raising red flags typically associated with automation or spoofing. Other possible results are "Suspicious" or "Not reliable". ## Scrape a Dynamically Loaded Page To demonstrate scraping client-side rendered data, I'll use the [JS-generated content page](https://quotes.toscrape.com/js/) generated version of the Quotes to Scrape website. The snippet below uses the Puppeteer-Incogniton API, via the `startIncogniton()` function you created earlier, to scrape a page in three steps: Navigate to a dynamically rendered page, wait for the content to fully render, and extract quotes and authors from the DOM. ```javascript const scrapeDynamicContent = async (profileId) => { try { // Start Incogniton browser const browser = await startIncogniton({ profileId }) const page = await browser.newPage() // Navigate to the dynamic page with client-side rendering await page.goto('https://quotes.toscrape.com/js/', { waitUntil: 'networkidle0', }) // Extract quotes and authors from dynamically rendered content const quotes = await page.$$eval('.quote', (elements) => elements.map((element) => ({ text: element && element.querySelector('.text').innerText.trim(), author: element && element.querySelector('.author').innerText.trim(), })), ) console.log('Extracted Quotes ->', quotes) // Close the browser after scraping await browser.close() } catch (error) { console.error('Error scraping dynamically loaded content ->', error) } } ``` Pay attention to the use of `.$$eval()` instead of the `.$eval()` method. It indicates that you intend to extract multiple quotes, not just a single element. The resulting output data should look like this: ```javascript Extracted Quotes -> [ { text: '"The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking."', author: 'Albert Einstein' }, { text: '"It is our choices, Harry, that show what we truly are, far more than our abilities."', author: 'J.K. Rowling' }, { text: '"The person, be it gentleman or lady, who has not pleasure in a good novel, must be intolerably stupid."', author: 'Jane Austen' }, // other quotes... ] ``` ## Handle Paginated Data Scraping In most day-to-day use cases, web scraping would typically involve discovering links on a page and recursively following them to additional pages, continuing this process until all relevant data has been gathered. In this section, you'll build a recursive function that navigates through all available pages on the site and collects the quotes from each one, using the `quotes.toscrape.com/js` page as the data source. ```javascript const scrapeRecursively = async ({ browser, givenPage, scrapeUrl, allData, }) => { try { // Use the provided page const page = givenPage await page.goto(scrapeUrl, { waitUntil: 'networkidle0' }) // Extract quotes from current page const quotes = await page.$$eval('.quote', (elements) => elements.map((el) => ({ text: el.querySelector('.text').innerText.trim(), author: el.querySelector('.author').innerText.trim(), })), ) // Add current page data to the collection allData.push(...quotes) // Look for next page link const nextLink = await page.$('li.next a') // If there's a next button, continue scraping if (nextLink) { const href = await nextLink.evaluate((el) => el.href) await scrapeRecursively({ givenPage: page, scrapeUrl: href, allData, }) } return { data: allData, } } catch (error) { console.error('Error scraping dynamically loaded content ->', error) throw error } } // Usage example const scrapeAllPages = async (profileId) => { try { const browser = await startIncogniton({ profileId }) const page = await browser.newPage() const allData = [] await scrapeRecursively({ browser, givenPage: page, scrapeUrl: 'https://quotes.toscrape.com/js/', allData, }) console.log('ALL SCRAPED DATA ->', allData) browser.close() } catch (err) { console.error(err) throw err } } ``` The function navigates to the URL, waits for the page to load, and extracts all quotes. Next, it checks for a "next page" link using the `li.next a` selector. If found, it constructs the full URL and recursively calls itself to scrape data from the next page until there are no further pages to scrape. There you have it! You have successfully scraped a website anonymously by connecting your Incogniton antidetect browser to Puppeteer via Chrome DevTools Protocol (CDP). And while this guide is for Puppeteer, the same [CDP url](https://api-docs.incogniton.com/apis#launch-puppeteer-custom) can also be used to integrate Incogniton with other CDP-compatible tools like Playwright. You can check out the complete source code for this tutorial [here](https://github.com/HAYVENO/anonymous-scraper). Incogniton's real fingerprints ensure your automation software doesn't come off as a bot, so as long as you stay responsible and ethical in its use, you're unlikely to get hit with annoying anti-bot prompts like CAPTCHAs. In those rare cases where you do get one, I'll dive into the solutions to that in a future article. ## Conclusion You have now learnt how to scrape dynamically loaded websites while maintaining privacy and security using Incogniton and Puppeteer. This approach helps you avoid being detected as a bot in most cases, reducing the likelihood of encountering CAPTCHAs and other anti-bot measures. However, while Incogniton's real fingerprints make your automation software less likely to be detected as a bot, you should always use these tools responsibly. Be mindful of each website's terms of service and uphold ethical scraping practices. - Respect robots.txt files - Implement reasonable rate limiting - Only collect publicly available data - Don't overload servers with requests Enjoy scraping anonymously. 🚀 --- # CLI Source: https://docs.incogniton.com/cli # Incogniton CLI The Incogniton CLI (`incogniton-cli`) lets you drive Incogniton straight from your terminal — no SDK or code required. Every endpoint of the [local automation API](/apis) is available as a command: list and inspect profiles, launch and stop browsers, manage cookies, and start Puppeteer or Selenium sessions, all from a shell. The CLI talks to the Incogniton app running on your own machine (`127.0.0.1`, default port `35000`), just like the SDKs and the REST API. Output is human-readable in the terminal and automatically switches to raw JSON when piped, so commands compose naturally into scripts and pipelines. The CLI requires a paid Incogniton subscription that includes automation, and the Incogniton desktop app must be running with the automation API enabled. ## Installation The CLI is installed and kept up to date by the Incogniton app itself — there is nothing to download manually. In the Incogniton app, go to Settings → Automation and click Download CLI. The app downloads the right binary for your platform, verifies it, and adds its folder to your PATH so you can run it from any terminal. The PATH change only applies to terminals opened after installation, so open a fresh terminal window. With the Incogniton app running, check that the CLI can reach it: ```bash incogniton-cli alive # OK ``` While installed, the CLI **updates automatically** whenever the Incogniton app starts — you never need to update it yourself. To remove it (including the `PATH` entry), use **Uninstall CLI** in the same Settings → Automation tab. The binary itself lives in a `cli` folder inside Incogniton's data directory: | Platform | Location | | -------- | ---------------------------------------------- | | Windows | `%APPDATA%\Incogniton\Incogniton\cli` | | macOS | `~/Library/Application Support/Incogniton/cli` | | Linux | `~/.local/share/Incogniton/cli` | ## Usage Commands are named after the API endpoints they call, and endpoint parameters become flags with the same name: ```bash incogniton-cli profile-get-all # list all profiles (table) incogniton-cli profile-get --id # one profile (detail view) incogniton-cli profile-launch --id # launch a profile's browser incogniton-cli profile-stop --id # stop it again ``` Run `incogniton-cli --help` for the full command list, or `incogniton-cli --help` for a command's flags. Two global flags work on every command: | Flag | Description | | -------------- | ------------------------------------------------------------------------------------------ | | `--port`, `-p` | Port the Incogniton automation API listens on (default `35000`) | | `--json` | Print the raw JSON response instead of formatted output | If your automation API runs on a non-default port (configurable in the app's Debug settings), pass it with --port on every command. ## Scripting and Pipelines In an interactive terminal the CLI prints formatted tables and detail views. As soon as output is **piped or redirected**, it switches to JSON automatically — no `--json` needed. For responses that wrap their data, the CLI emits the data itself (the profile document or list) rather than the `status` envelope, so output feeds directly into tools like `jq` or straight back into other CLI commands: ```bash # All profile ids, one per line incogniton-cli profile-get-all | jq -r '.[].general_profile_information.browser_id' # Clone a profile: fetch its document and add it back (the server assigns a new id) incogniton-cli profile-get --id | incogniton-cli profile-add ``` A failed request prints the server's error message and exits with a non-zero status code, so shell scripts can detect failures the usual way (`if`, `&&`, `set -e`). ## Sending Profile Documents `profile-add` and `profile-update` send a full profile JSON document, which they accept in three ways: ```bash incogniton-cli profile-add --data @profile.json # from a file incogniton-cli profile-add --data '{"general_profile_information":{...}}' # inline cat profile.json | incogniton-cli profile-add # from stdin ``` See the [API reference](/apis) for the profile document structure. ## Command Reference Every command maps one-to-one to an endpoint of the local automation API, with the same parameters, responses, and error shapes. The [API reference](/apis) documents them all — each endpoint includes a ready-to-run example on its **CLI** tab, alongside the cURL and SDK versions. You can also run `incogniton-cli --help` for the full command list at any time. ## Next Steps Full parameter and response documentation for every endpoint — and therefore every CLI command. Step-by-step tutorials for automating your Incogniton profiles with Puppeteer, Playwright, and Selenium. --- Need help? Join our [community](https://t.me/incognitonOfficial) or [contact support](https://incogniton.com/contact/). --- --- # Contacts Source: https://docs.incogniton.com/contacts # Contacts As the name suggests, contacts are a core part of Protocol — the very reason Protocol exists is so you can have secure conversations with your contacts. On this page, we'll dive into the different contact endpoints you can use to manage contacts programmatically. We'll look at how to query, create, update, and delete contacts. ## The contact model The contact model contains all the information about your contacts, such as their username, avatar, and phone number. It also contains a reference to the conversation between you and the contact and information about when they were last active on Protocol. ### Properties - **id** (string) Unique identifier for the contact. - **username** (string) The username for the contact. - **phone_number** (string) The phone number for the contact. - **avatar_url** (string) The avatar image URL for the contact. - **display_name** (string) The contact display name in the contact list. By default, this is just the username. - **conversation_id** (string) Unique identifier for the conversation associated with the contact. - **last_active_at** (timestamp) Timestamp of when the contact was last active on the platform. - **created_at** (timestamp) Timestamp of when the contact was created. --- ## List all contacts This endpoint allows you to retrieve a paginated list of all your contacts. By default, a maximum of ten contacts are shown per page. - **filter** (object) - **age** (integer) - **min** (integer) Minimum age of contacts to return. - **max** (integer) Maximum age of contacts to return. Filter contacts by age. - **status** (string) Filter contacts by status. Filter criteria for the contacts. - **limit** (integer) Limit the number of contacts returned. ```bash curl -G https://api.protocol.chat/v1/contacts \ -H "Authorization: Bearer {token}" \ -d active=true \ -d limit=10 ``` ```js import ApiClient from '@example/protocol-api' const client = new ApiClient(token) await client.contacts.list() ``` ```python from protocol_api import ApiClient client = ApiClient(token) client.contacts.list() ``` ```php $client = new \Protocol\ApiClient($token); $client->contacts->list(); ``` ```json { "has_more": false, "data": [ { "id": "WAz8eIbvDR60rouK", "username": "FrankMcCallister", "phone_number": "1-800-759-3000", "avatar_url": "https://assets.protocol.chat/avatars/frank.jpg", "display_name": null, "conversation_id": "xgQQXg3hrtjh7AvZ", "last_active_at": 705103200, "created_at": 692233200 }, { "id": "hSIhXBhNe8X1d8Et" // ... } ] } ``` --- ## Create a contact This endpoint allows you to add a new contact to your contact list in Protocol. To add a contact, you must provide their Protocol username and phone number. ### Required attributes - **username** (string) The username for the contact. - **phone_number** (string) The phone number for the contact. ### Optional attributes - **avatar_url** (string) The avatar image URL for the contact. - **display_name** (string) The contact display name in the contact list. By default, this is just the username. ```bash curl https://api.protocol.chat/v1/contacts \ -H "Authorization: Bearer {token}" \ -d username="FrankMcCallister" \ -d phone_number="1-800-759-3000" \ -d avatar_url="https://assets.protocol.chat/avatars/frank.jpg" ``` ```js import ApiClient from '@example/protocol-api' const client = new ApiClient(token) await client.contacts.create({ username: 'FrankMcCallister', phone_number: '1-800-759-3000', avatar_url: 'https://assets.protocol.chat/avatars/frank.jpg', }) ``` ```python from protocol_api import ApiClient client = ApiClient(token) client.contacts.create( username="FrankMcCallister", phone_number="1-800-759-3000", avatar_url="https://assets.protocol.chat/avatars/frank.jpg", ) ``` ```php $client = new \Protocol\ApiClient($token); $client->contacts->create([ 'username' => 'FrankMcCallister', 'phone_number' => '1-800-759-3000', 'avatar_url' => 'https://assets.protocol.chat/avatars/frank.jpg', ]); ``` ```json { "id": "WAz8eIbvDR60rouK", "username": "FrankMcCallister", "phone_number": "1-800-759-3000", "avatar_url": "https://assets.protocol.chat/avatars/frank.jpg", "display_name": null, "conversation_id": "xgQQXg3hrtjh7AvZ", "last_active_at": null, "created_at": 692233200 } ``` --- ## Retrieve a contact This endpoint allows you to retrieve a contact by providing their Protocol id. Refer to [the list](#the-contact-model) at the top of this page to see which properties are included with contact objects. ```bash curl https://api.protocol.chat/v1/contacts/WAz8eIbvDR60rouK \ -H "Authorization: Bearer {token}" ``` ```js import ApiClient from '@example/protocol-api' const client = new ApiClient(token) await client.contacts.get('WAz8eIbvDR60rouK') ``` ```python from protocol_api import ApiClient client = ApiClient(token) client.contacts.get("WAz8eIbvDR60rouK") ``` ```php $client = new \Protocol\ApiClient($token); $client->contacts->get('WAz8eIbvDR60rouK'); ``` ```json { "id": "WAz8eIbvDR60rouK", "username": "FrankMcCallister", "phone_number": "1-800-759-3000", "avatar_url": "https://assets.protocol.chat/avatars/frank.jpg", "display_name": null, "conversation_id": "xgQQXg3hrtjh7AvZ", "last_active_at": 705103200, "created_at": 692233200 } ``` --- ## Update a contact This endpoint allows you to perform an update on a contact. Currently, the only attribute that can be updated on contacts is the `display_name` attribute which controls how a contact appears in your contact list in Protocol. ### Optional attributes - **display_name** (string) The contact display name in the contact list. By default, this is just the username. ```bash curl -X PUT https://api.protocol.chat/v1/contacts/WAz8eIbvDR60rouK \ -H "Authorization: Bearer {token}" \ -d display_name="UncleFrank" ``` ```js import ApiClient from '@example/protocol-api' const client = new ApiClient(token) await client.contacts.update('WAz8eIbvDR60rouK', { display_name: 'UncleFrank', }) ``` ```python from protocol_api import ApiClient client = ApiClient(token) client.contacts.update("WAz8eIbvDR60rouK", display_name="UncleFrank") ``` ```php $client = new \Protocol\ApiClient($token); $client->contacts->update('WAz8eIbvDR60rouK', [ 'display_name' => 'UncleFrank', ]); ``` ```json { "id": "WAz8eIbvDR60rouK", "username": "FrankMcCallister", "phone_number": "1-800-759-3000", "avatar_url": "https://assets.protocol.chat/avatars/frank.jpg", "display_name": "UncleFrank", "conversation_id": "xgQQXg3hrtjh7AvZ", "last_active_at": 705103200, "created_at": 692233200 } ``` --- ## Delete a contact This endpoint allows you to delete contacts from your contact list in Protocol. Note: This will also delete your conversation with the given contact. ```bash curl -X DELETE https://api.protocol.chat/v1/contacts/WAz8eIbvDR60rouK \ -H "Authorization: Bearer {token}" ``` ```js import ApiClient from '@example/protocol-api' const client = new ApiClient(token) await client.contacts.delete('WAz8eIbvDR60rouK') ``` ```python from protocol_api import ApiClient client = ApiClient(token) client.contacts.delete("WAz8eIbvDR60rouK") ``` ```php $client = new \Protocol\ApiClient($token); $client->contacts->delete('WAz8eIbvDR60rouK'); ``` --- # Errors Source: https://docs.incogniton.com/errors # Errors In this guide, we will talk about what happens when something goes wrong while you work with the API. Mistakes happen, and mostly they will be yours, not ours. Let's look at some status codes and error types you might encounter. You can tell if your request was successful by checking the status code when receiving an API response. If a response comes back unsuccessful, you can use the error type and error message to figure out what has gone wrong and do some rudimentary debugging (before contacting support). Before reaching out to support with an error, please be aware that 99% of all reported errors are, in fact, user errors. Therefore, please carefully check your code before contacting incognitionsupport. --- ## Status codes Here is a list of the different categories of status codes returned by the incognition API . Use these to understand if a request was successful. A 2xx status code indicates a successful response. A 4xx status code indicates a client error — this means it's a _you_ problem. A 5xx status code indicates a server error — you won't be seeing these. --- ## Error types Whenever a request is unsuccessful, the incognition API will return an error response with an error type and message. You can use this information to understand better what has gone wrong and how to fix it. Most of the error messages are pretty helpful and actionable. Here is a list of the two error types supported by the incognition API — use these to understand what you have done wrong. This means that we made an error, which is highly speculative and unlikely. This means that you made an error, which is much more likely. ```bash { "type": "api_error", "message": "No way this is happening!?", "documentation_url": "https://incognition.chat/docs/errors/api_error" } ```