This pattern launches an isolated Multilogin profile via API, attaches Playwright through CDP, runs automation, and always stops the profile in a finally block.

Environment setup

pip install playwright httpx
playwright install chromium
export MLX_TOKEN="your_api_token"
export MLX_PROFILE_ID="your_profile_uuid"

Launch + Playwright attach

import os
import asyncio
import httpx
from playwright.async_api import async_playwright

MLX = "https://api.multilogin.com"  # verify current base URL in docs
TOKEN = os.environ["MLX_TOKEN"]
PROFILE = os.environ["MLX_PROFILE_ID"]

async def run():
    headers = {"Authorization": f"Bearer {TOKEN}"}
    async with httpx.AsyncClient(timeout=60) as client:
        r = await client.post(
            f"{MLX}/profile/start",  # endpoint name varies by API version
            headers=headers,
            json={"profile_id": PROFILE, "headless": False},
        )
        r.raise_for_status()
        data = r.json()
        cdp_url = data["cdp_url"]  # field name per API response

    pw = await async_playwright().start()
    try:
        browser = await pw.chromium.connect_over_cdp(cdp_url)
        context = browser.contexts[0] if browser.contexts else await browser.new_context()
        page = context.pages[0] if context.pages else await context.new_page()
        await page.goto("https://example.com", wait_until="domcontentloaded")
        print(await page.title())
    finally:
        await pw.stop()
        async with httpx.AsyncClient(timeout=30) as client:
            await client.post(f"{MLX}/profile/stop", headers=headers, json={"profile_id": PROFILE})

asyncio.run(run())

Error handling checklist

Related

Disclosure: MLX-MMO affiliated with Multilogin. Endpoint paths may change — verify against official API docs. Promo: SAAS50 / MIN50.