--- title: Migrating to Lightcone | Lightcone description: Move from local browser automation (Selenium, Puppeteer, Playwright) to Lightcone cloud browsers. --- If you’re already using Selenium, Puppeteer, or Playwright for browser automation, Lightcone replaces the browser infrastructure with managed cloud sessions. This guide maps the concepts and APIs you already know to their Lightcone equivalents. ## Why migrate | | Local automation | Lightcone | | -------------------- | -------------------------------------------------- | ------------------------------------------------------- | | **Infrastructure** | You manage browser binaries, drivers, containers | Managed cloud browsers — nothing to install or maintain | | **Scaling** | Limited by your machine’s resources | Spin up hundreds of sessions on demand | | **Bot detection** | You configure fingerprinting, proxies, user agents | Built-in stealth with optional advanced proxy | | **AI agents** | You build the agent loop yourself | Agent Tasks run autonomously from a single instruction | | **Persistent state** | You manage cookie files or browser profiles | `persistent: true` saves and restores automatically | | **Cost** | Free (but you pay for infrastructure) | Pay-per-session, no infrastructure to manage | ## Concept mapping | Local concept | Lightcone equivalent | | ------------------------------ | ----------------------------------------------------------------------------------------------------------- | | Browser instance / page | [Computer session](/guides/computers/index.md) (`kind: "browser"`) | | `page.goto(url)` | `computer.navigate(url)` | | `page.click(selector)` | `computer.click(x, y)` (screenshot-based coordinates) | | `page.type(selector, text)` | `computer.type(text)` (types into focused element) | | `page.keyboard.press('Enter')` | `computer.hotkey("Enter")` | | `page.screenshot()` | `computer.screenshot()` → URL of the captured image | | `page.content()` | `computer.html()` → page HTML content | | `page.evaluate(js)` | `computer.debug(command)` for shell, or use [Playwright CDP](/integrations/playwright/index.md) for JS eval | | `page.waitForSelector()` | `computer.wait(seconds)` + screenshot to verify | | `browser.close()` | `computer.terminate()` or context manager exit | | Cookie files / profiles | [Persistent sessions](/guides/computers#persistent-sessions/index.md) (`persistent: true`) | | Proxy config | `use_advanced_proxy: true` or `change_proxy()` | ## From Selenium **Before (Selenium):** ``` from selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("https://example.com") driver.find_element(By.CSS_SELECTOR, "#search").send_keys("hello") driver.find_element(By.CSS_SELECTOR, "#submit").click() screenshot = driver.get_screenshot_as_png() driver.quit() ``` **After (Lightcone):** ``` from tzafon import Lightcone client = Lightcone() with client.computer.create(kind="browser") as computer: computer.navigate("https://example.com") computer.wait(2) # Instead of CSS selectors, use screenshot-based coordinates # Take a screenshot to find field positions result = computer.screenshot() print(computer.get_screenshot_url(result)) # Click the search field and type computer.click(400, 300) # Coordinates from screenshot computer.type("hello") # Click submit computer.click(500, 400) computer.wait(2) result = computer.screenshot() print(computer.get_screenshot_url(result)) ``` Key differences: - **No driver setup** — no ChromeDriver, no version matching, no Docker - **Coordinate-based interaction** — take a screenshot, find the element position, click at those coordinates - **Automatic cleanup** — context manager handles session termination - **Cloud execution** — the browser runs in Lightcone’s cloud, not on your machine ## From Puppeteer **Before (Puppeteer):** ``` import puppeteer from "puppeteer"; const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto("https://example.com"); await page.type("#search", "hello"); await page.click("#submit"); await page.screenshot({ path: "result.png" }); await browser.close(); ``` **After (Lightcone):** ``` import Lightcone from "@tzafon/lightcone"; const client = new Lightcone(); const computer = await client.computers.create({ kind: "browser" }); const id = computer.id!; try { await client.computers.navigate(id, { url: "https://example.com" }); await new Promise((r) => setTimeout(r, 2000)); // Screenshot to find coordinates const screenshot = await client.computers.screenshot(id); console.log("Layout:", screenshot.result?.screenshot_url); // Click and type using coordinates await client.computers.click(id, { x: 400, y: 300 }); await client.computers.type(id, { text: "hello" }); await client.computers.click(id, { x: 500, y: 400 }); const result = await client.computers.screenshot(id); console.log("Result:", result.result?.screenshot_url); } finally { await client.computers.delete(id); } ``` ## From Playwright Lightcone has a [Playwright integration](/integrations/playwright/index.md) that lets you keep using Playwright’s selector-based API while running on Lightcone cloud browsers. This is the easiest migration path: **Before (Playwright local):** ``` from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.goto("https://example.com") page.fill("#search", "hello") page.click("#submit") page.screenshot(path="result.png") browser.close() ``` **After (Playwright + Lightcone):** ``` from playwright.sync_api import sync_playwright from tzafon import Lightcone client = Lightcone() session = client.computers.create(kind="browser") with sync_playwright() as p: # Connect to the Lightcone session via CDP browser = p.chromium.connect_over_cdp(f"wss://api.tzafon.ai/v1/cdp/{session.id}") page = browser.contexts[0].pages[0] page.goto("https://example.com") page.fill("#search", "hello") page.click("#submit") page.screenshot(path="result.png") browser.close() client.computers.delete(session.id) ``` This approach lets you keep your CSS selectors and Playwright test patterns while gaining cloud infrastructure, stealth, and scaling. The Playwright integration is the recommended path if you have existing Playwright tests or scripts. You get the best of both worlds: familiar selectors with cloud infrastructure. ## Use AI instead of selectors Lightcone’s biggest advantage over local automation is AI-powered interaction. Instead of maintaining brittle selectors, let a vision model find elements: **The old way (selector-based):** ``` # Breaks when the site changes its HTML page.click("#submit-btn") page.fill("input[name='email']", "user@example.com") ``` **The Lightcone way (AI agent):** ``` # Works regardless of HTML structure for event in client.agent.tasks.start_stream( instruction=( "Go to example.com, " "enter user@example.com in the email field, " "and click the submit button." ), kind="browser", max_steps=10, ): print(event) ``` **The Lightcone way (CUA loop for custom logic):** ``` # You control each step, but AI finds the elements response = client.responses.create( model="tzafon.northstar-cua-fast", input=[{ "role": "user", "content": [ {"type": "input_text", "text": "Click the email field and type user@example.com"}, {"type": "input_image", "image_url": screenshot_url}, ], }], tools=[{"type": "computer_use", "display_width": 1280, "display_height": 720, "environment": "browser"}], ) # The model returns coordinates to click — execute them on the session ``` ## Migration checklist - [ ] Install the SDK: `pip install tzafon` or `npm install @tzafon/lightcone` - [ ] Get an API key from the [dashboard](https://lightcone.ai/developer) - [ ] Replace browser launch with `client.computer.create(kind="browser")` - [ ] Replace selector-based clicks with coordinate-based clicks (or use the [Playwright integration](/integrations/playwright/index.md)) - [ ] Replace `waitForSelector` with `computer.wait()` + screenshot verification - [ ] Replace local cookie/profile management with `persistent: true` - [ ] Replace proxy configuration with `use_advanced_proxy: true` - [ ] Consider replacing coordinate-based scripts with [Agent Tasks](/guides/agent-tasks/index.md) for resilience ## See also - [**Quickstart**](/guides/quickstart/index.md) — get started in under 5 minutes - [**Computers**](/guides/computers/index.md) — full session API reference - [**Playwright integration**](/integrations/playwright/index.md) — use Playwright selectors on Lightcone browsers - [**Agent Tasks**](/guides/agent-tasks/index.md) — AI-powered automation without coordinates - [**Best practices**](/guides/best-practices/index.md) — patterns for reliable automation