--- title: Computers | Lightcone description: Sandboxed browser and desktop sessions you create, interact with, and terminate. --- A **computer** is a sandboxed cloud environment — either a Chromium browser or a full Linux desktop — that you control through the Lightcone API. Each session runs in an isolated container with its own browser profile, filesystem, and network. You create a session, send actions (click, type, navigate, screenshot), and terminate it when done. ## Browser vs. desktop | | Browser | Desktop | | -------------- | ----------------------------------- | --------------------------------------------------------- | | `kind` | `"browser"` | `"desktop"` | | Environment | Headless Chromium with stealth | Full Linux desktop (X11) | | Use cases | Web scraping, form filling, testing | OS-level automation, file management, multi-app workflows | | Tab management | Yes | No | | Proxy support | Yes | No | | File system | Isolated per session | Full Linux filesystem | ## Session lifecycle ### Create ``` from tzafon import Lightcone client = Lightcone() # High-level wrapper with automatic cleanup with client.computer.create(kind="browser") as computer: computer.navigate("https://example.com") # session terminates when block exits ``` ``` import Lightcone from "@tzafon/lightcone"; const client = new Lightcone(); const computer = await client.computers.create({ kind: "browser" }); await client.computers.navigate(computer.id!, { url: "https://example.com" }); // Always clean up when done await client.computers.delete(computer.id!); ``` ### Interact Every action returns an `ActionResult` containing a `status`, optional `result` data (a dictionary with action-specific keys), and optional `page_context` with viewport state. ``` computer.navigate("https://example.com") computer.click(100, 200) computer.type("hello world") computer.hotkey("enter") computer.scroll(0, 300, 640, 400) # dx, dy, x, y result = computer.screenshot() url = computer.get_screenshot_url(result) # extracts result["screenshot_url"] html_result = computer.html() content = computer.get_html_content(html_result) # extracts result["html_content"] ``` ``` const id = computer.id!; await client.computers.navigate(id, { url: "https://example.com" }); await client.computers.click(id, { x: 100, y: 200 }); await client.computers.type(id, { text: "hello world" }); await client.computers.hotkey(id, { keys: ["Enter"] }); await client.computers.scroll(id, { dx: 0, dy: 300, x: 640, y: 400 }); const result = await client.computers.screenshot(id); const url = result.result?.screenshot_url as string; const htmlResult = await client.computers.html(id); const content = htmlResult.result?.html_content as string; ``` The `result` dictionary contains different keys depending on the action: | Action | Key | Value | | -------------- | ---------------- | ------------------------------ | | `screenshot()` | `screenshot_url` | URL of the captured screenshot | | `html()` | `html_content` | The page’s HTML as a string | | `debug()` | `debug_response` | Shell command output | ### Terminate ``` # Automatic with context manager (recommended) with client.computer.create(kind="browser") as computer: # ... # Or manual cleanup session = client.computers.create(kind="browser") # ... client.computers.delete(session.id) ``` ``` await client.computers.delete(computer.id!); ``` ## ComputerSession (high-level wrapper) Both SDKs provide a `ComputerSession` class that binds a session ID to convenience methods, so you don’t have to pass the ID on every call. **Python** — accessed via `client.computer.create()` with a context manager: ``` with client.computer.create(kind="browser") as computer: computer.navigate("https://example.com") computer.click(100, 200) result = computer.screenshot() url = computer.get_screenshot_url(result) # Session terminates automatically on exit ``` **TypeScript** — imported from the package and created with `ComputerSession.create()`: ``` import Lightcone, { ComputerSession } from "@tzafon/lightcone"; const client = new Lightcone(); const computer = await ComputerSession.create(client, { kind: "browser" }); try { await computer.navigate("https://example.com"); await computer.click(100, 200); const result = await computer.screenshot(); const url = ComputerSession.getScreenshotUrl(result); } finally { await computer.terminate(); } ``` Both wrappers expose the same methods: `navigate()`, `click()`, `type()`, `hotkey()`, `scroll()`, `screenshot()`, `html()`, `wait()`, `batch()`, and `keepAlive()`. Static helper methods `getScreenshotUrl()`, `getHtmlContent()`, and `getDebugResponse()` extract values from `ActionResult`. The examples in these docs use the lower-level `client.computers` resource for explicitness, but `ComputerSession` is the recommended approach for most use cases. ## Actions reference ### Mouse | Action | Description | | ---------------------- | --------------------------------- | | `click(x, y)` | Left-click at pixel coordinates | | `double_click(x, y)` | Double-click | | `right_click(x, y)` | Right-click (context menu) | | `drag(x1, y1, x2, y2)` | Click-and-drag between two points | | `mouse_down(x, y)` | Press and hold the mouse button | | `mouse_up(x, y)` | Release the mouse button | ### Keyboard | Action | Description | | --------------- | -------------------------------------------------- | | `type(text)` | Type text into the focused element | | `hotkey(keys)` | Press a key combination (e.g., `["Control", "c"]`) | | `key_down(key)` | Press and hold a key | | `key_up(key)` | Release a held key | ### Navigation & viewport | Action | Description | | ------------------------- | ---------------------------- | | `navigate(url)` | Go to a URL | | `scroll(dx, dy, x, y)` | Scroll at position by delta | | `viewport(width, height)` | Resize the viewport | | `screenshot()` | Capture the current viewport | | `html()` | Get the page HTML | Coordinates are screenshot pixel positions. If you see a button at pixel (500, 300) in a screenshot, send `x=500, y=300`. ## Timeouts and keepalive Sessions have two timeout mechanisms: | Parameter | Default | Description | | ---------------------------- | -------------- | ---------------------------------------------- | | `timeout_seconds` | Plan-dependent | Maximum total session lifetime | | `inactivity_timeout_seconds` | Plan-dependent | Time with no API calls before auto-termination | | `auto_kill` | `true` | Whether the inactivity timeout is active | To keep a session alive during long pauses: ``` computer.keep_alive() ``` ``` await client.computers.keepalive(computer.id!); ``` ## Persistent sessions Save browser state (cookies, local storage) and restore it later: ``` # Save state on termination with client.computer.create(kind="browser", persistent=True) as computer: computer.navigate("https://example.com/login") # ... log in ... # State saved automatically when session ends # Restore state later using the session ID with client.computer.create( kind="browser", environment_id="previous_session_id", persistent=True, # save again on exit ) as computer: computer.navigate("https://example.com/dashboard") # Cookies are still active ``` ``` // Save state const session = await client.computers.create({ kind: "browser", persistent: true, }); // ... use the session, then terminate ... await client.computers.delete(session.id!); // Restore state const restored = await client.computers.create({ kind: "browser", environment_id: session.id!, persistent: true, }); ``` ## Batch actions Execute multiple actions in a single request. The batch stops on the first error: ``` results = client.computers.batch(session.id, actions=[ {"type": "navigate", "url": "https://example.com"}, {"type": "click", "x": 100, "y": 200}, {"type": "screenshot"}, ]) ``` ``` const results = await client.computers.batch(computer.id!, { actions: [ { type: "navigate", url: "https://example.com" }, { type: "click", x: 100, y: 200 }, { type: "screenshot" }, ], }); ``` ## Proxy support Route browser traffic through a proxy for stealth: ``` # Use the built-in advanced proxy with client.computer.create( kind="browser", use_advanced_proxy=True, ) as computer: # ... # Or change proxy mid-session client.computers.change_proxy(session.id, proxy_url="http://proxy.example.com:8080") ``` ``` const computer = await client.computers.create({ kind: "browser", use_advanced_proxy: true, }); // Change proxy mid-session await client.computers.changeProxy(computer.id!, { proxy_url: "http://proxy.example.com:8080", }); ``` Many websites actively block automation. Always check a site’s `robots.txt` and terms of service before automating. ## See also - [**Automate a browser**](/guides/automate-a-browser/index.md) — step-by-step walkthrough with a real example - [**Browser tabs**](/guides/browser-tabs/index.md) — multi-tab workflows - [**Shell commands**](/guides/shell-commands/index.md) — run terminal commands on sessions - [**Troubleshooting**](/guides/troubleshooting/index.md) — common issues and solutions - [**How Lightcone works**](/guides/how-lightcone-works/index.md) — architecture and session lifecycle