Skip to content

Automation API

Virtual Browser is Chromium-based. You can automate it with Playwright or other Chromium tools.

Pro feature

Local REST API, MCP, and CLI mode require a Pro membership. Copy http://localhost:{port} and your api-key from the client API menu.

Python example

python
import asyncio
import json
import requests
from playwright.async_api import async_playwright


class PlaywrightManager:
    """Manages browser contexts and pages."""

    def __init__(self):
        self.contexts = {}
        self.pages = {}

    async def get_context(self, context_id):
        if context_id in self.contexts:
            return self.contexts[context_id]
        context = await self.browser.new_context()
        self.contexts[context_id] = context
        return context

    async def get_page(self, context_id, page_id):
        context = await self.get_context(context_id)
        if context_id not in self.pages:
            self.pages[context_id] = {}
        if page_id in self.pages[context_id]:
            return self.pages[context_id][page_id]
        page = await context.new_page()
        self.pages[context_id][page_id] = page
        return page

    async def launch_browser(self):
        async with async_playwright() as p:
            self.browser = await p.chromium.launch(headless=False)

    async def close_browser(self):
        await self.browser.close()


async def main():
    manager = PlaywrightManager()
    await manager.launch_browser()

    # Use port and api-key from the client API menu
    BASE_URL = "http://localhost:9000"
    data = {"id": 1}
    headers = {
        "Content-Type": "application/json",
        "api-key": "YOUR_API_KEY",
    }

    try:
        response = requests.post(
            f"{BASE_URL}/api/launchBrowser",
            headers=headers,
            data=json.dumps(data),
        )
        response_data = response.json()
        print("Launch response:", response_data)
    except Exception as err:
        print(f"Launch failed: {err}")
        return

    if not response_data.get("success"):
        print("Launch failed")
        return

    debugging_port = response_data.get("data", {}).get("debuggingPort")
    if not debugging_port:
        print("No debugging port in response")
        return

    async with async_playwright() as p:
        manager.browser = await p.chromium.connect_over_cdp(
            f"http://localhost:{debugging_port}"
        )

        contexts = manager.browser.contexts
        if contexts:
            context = contexts[0]
            manager.contexts["default"] = context
            page = await context.new_page()
            if "default" not in manager.pages:
                manager.pages["default"] = {}
            manager.pages["default"]["main"] = page
        else:
            context = await manager.get_context("default")
            page = await manager.get_page("default", "main")

        await page.goto("https://example.com")

        try:
            stop_response = requests.post(
                f"{BASE_URL}/api/stopBrowser",
                headers=headers,
                data=json.dumps(data),
            )
            stop_response_data = stop_response.json()
            print("Stop response:", stop_response_data)
            if not stop_response_data.get("success"):
                print("Stop via API failed")
        except Exception as err:
            print(f"Stop error: {err}")


if __name__ == "__main__":
    asyncio.run(main())