Coming from another tool
Most scripts move to Echidna with a few changed lines: Echidna starts the browser with its fingerprint and proxy in place, and your code attaches to it over the DevTools protocol (CDP) instead of launching its own.
Before you start
- Open Settings → Automation & API, switch on Allow scripts and AI agents and copy your automation token. Store it in an environment variable, for example
ECHIDNA_API_TOKEN. - Create or import the profiles you want to use (see below), each with its proxy.
- Keep the Echidna app open while your scripts run.
Every script then follows the same pattern from the Engine API guide: start a profile, attach to its cdp_url, work in the profile's own context, stop the profile.
Paced or raw. Connect to cdp_url and Echidna paces your library's clicks and keys like a hand: a mouse path and a pause before each press, human key timing. raw_cdp_url, in the same answer, skips that: fastest, but raw automation input. Most scripts should stay on cdp_url; use raw_cdp_url only where every millisecond counts.
From Playwright
Replace launch() or launch_persistent_context() with a start call and connect_over_cdp, and use the profile's existing context instead of new_context().
| Before | With Echidna |
|---|---|
browser = p.chromium.launch(proxy=…) | info = requests.post(f"{API}/profiles/{NAME}/start", params={"headless": "true"}, headers=H).json()browser = p.chromium.connect_over_cdp(info["cdp_url"]) |
context = browser.new_context(user_agent=…, viewport=…, locale=…) | context = browser.contexts[0] with no options |
context.storage_state(path=…) to keep logins | Nothing: the profile keeps its cookies and storage between runs |
browser.close() | requests.post(f"{API}/profiles/{NAME}/stop", headers=H), which saves cookies |
Pages, locators, waits and assertions work unchanged. To move a saved Playwright storageState file into a profile, import it on the profile's Cookies tab: cookie import accepts Playwright JSON.
From Puppeteer
Switch to puppeteer-core (Echidna provides the browser, so no bundled Chromium is needed) and replace launch() with connect():
import puppeteer from "puppeteer-core";
const info = await (await fetch(`${API}/profiles/${NAME}/start?headless=true`,
{ method: "POST", headers: H })).json();
const browser = await puppeteer.connect({ browserWSEndpoint: info.cdp_url, defaultViewport: null });
const page = await browser.newPage();
// ... your existing page code ...
browser.disconnect();
await fetch(`${API}/profiles/${NAME}/stop`, { method: "POST", headers: H });
- Drop
puppeteer-extra-plugin-stealthand similar plugins, and calls such aspage.setUserAgent,page.setViewport,page.emulateTimezoneand proxy arguments. - Pass
defaultViewport: nullso Puppeteer keeps the profile's own window size. - Call
browser.disconnect()and then the stop route, rather thanbrowser.close(), so Echidna closes the browser and saves its cookies.
From Selenium
Selenium attaches to the running profile through Chrome's debuggerAddress option, using the webdriver field of the start answer:
info = requests.post(f"{API}/profiles/{NAME}/start", headers=H).json()
opts = webdriver.ChromeOptions()
opts.add_experimental_option("debuggerAddress", info["webdriver"]) # 127.0.0.1:PORT
driver = webdriver.Chrome(options=opts)
- chromedriver is still needed. Selenium talks to the browser through chromedriver, so you need a chromedriver whose major version matches the profile's Chrome version. Remove other
ChromeOptionssuch as arguments, user agent and proxy: they don't apply to a browser that is already running. - Drop
undetected-chromedriverand similar patches; Echidna's browser is already set up. - Finish with the stop route so cookies are saved.
If you are rewriting anyway, Playwright and Puppeteer connect to cdp_url directly and need no driver.
From another anti-detect browser
Moving from AdsPower, GoLogin, Multilogin or a similar tool means recreating your profiles in Echidna. Echidna doesn't copy another tool's fingerprints: each profile gets a new, coherent device from Echidna.
Profiles
Choose Import profiles above the profile table. Import reads AdsPower, GoLogin and Multilogin export files, Echidna CSV or JSON, a TabSentry tasks CSV, and plain text with one profile per line (name, name:proxy or just a proxy). From another tool's export it brings over each profile's name, proxy, group, tags and notes. Every imported profile gets its own new fingerprint. When a name already exists you can skip it, import it with a new name or update the existing profile.
Scripts can do the same with POST /profiles/import using the automation token, or create profiles one by one with POST /profiles.
Logins and cookies
- Import cookies on a profile's Cookies tab, or into the selected profiles at once from Tools… → Browser data → Import cookies into all…. Accepted: Echidna or Playwright JSON, EditThisCookie or Cookie-Editor JSON, and Netscape
cookies.txt. - From a Chrome profile folder, Import profiles → Chrome profile folder creates a new profile with that folder's cookies. On macOS and Windows, cookies that Chrome locks with the system keychain can't be read.
- Sites may still ask you to sign in again, because the new profile presents a different device than the one the session was created on.
Proxies
Paste your proxy list into Proxies → Add proxies (one per line), press Check all, then assign proxies to profiles. See Proxies and location for the supported formats.
Let Echidna choose the devices
- Don't try to recreate your old user agents, screen sizes, WebGL or canvas values. Echidna picks a real, consistent device for each profile, the same kind of computer you run it on, and keeps it stable across launches (see Fingerprints and personas).
- Timezone, geolocation and the WebRTC address follow each profile's proxy (unless you set them yourself), so choose the proxy and let Echidna set the rest. The language follows your computer unless you set one per profile.
- Creating profiles needs an internet connection and a signed-in app, because fingerprints come from Echidna's servers.
Your automation
If you drove the other tool through its local API (start a profile, receive a DevTools or WebSocket address, connect Playwright, Puppeteer or Selenium), the same shape works here:
| Step | Echidna |
|---|---|
| Authenticate | Authorization: Bearer <automation token> on every request |
| Find the API | ~/.echidna/api-port, or a fixed port from Settings → Automation & API |
| List profiles | GET /profiles |
| Start and get the address | POST /profiles/{name}/start → cdp_url (and webdriver for Selenium) |
| Stop | POST /profiles/{name}/stop |
Profiles are addressed by their name rather than an id. Flows, schedules and the MCP server for AI agents are there when you want Echidna to run the work for you.