Skip to content

Playwright

Playwright attaches over CDP with connect_over_cdp() in Python and connectOverCDP() in Node.js. Get the URL from /connect, hand it over, and use Playwright normally.

import httpx
from playwright.sync_api import sync_playwright
API = "https://browser.rayobyte.com"
KEY = "rb_live_YOUR_KEY"
PROXY = "http://USERNAME:[email protected]:8000"
resp = httpx.get(
f"{API}/connect",
params={"os": "windows", "proxy": PROXY},
headers={"x-api-key": KEY},
timeout=120,
)
if resp.status_code != 200:
raise SystemExit(f"{resp.status_code}: {resp.text}")
cdp_url = resp.text.strip()
session_id = resp.headers["x-session-id"]
try:
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(cdp_url)
context = browser.contexts[0]
page = context.pages[0] if context.pages else context.new_page()
page.goto("https://quotes.toscrape.com/")
print(page.title()) # Quotes to Scrape
finally:
httpx.post(
f"{API}/api/browser/close",
json={"browserId": session_id},
headers={"x-api-key": KEY},
timeout=30,
)

browser.close() does not stop a browser Playwright attached to over CDP. It disconnects Playwright and the session keeps running, with its tabs and cookies, until the lifetime ends at 7,200 seconds by default. The close call in finally is what ends it. To keep the browser for a later run instead, skip that call, store the x-session-id value and reconnect.

Take browser.contexts[0] rather than calling new_context(). A new context applies Playwright’s default 1280×720 viewport emulation, so the page then reports a screen and window size that disagree with each other and with the session’s profile: outerWidth ends up smaller than innerWidth, which no real Chrome window does.

If you need a second context, pass no_viewport=True (noViewport: true in Node.js) so it keeps the real window size.

from rayobrowse import Rayobrowse
from playwright.sync_api import sync_playwright
PROXY = "http://USERNAME:[email protected]:8000"
client = Rayobrowse(endpoint="https://browser.rayobyte.com", api_key="rb_live_YOUR_KEY")
ws_url = client.connect_url(os="windows", proxy=PROXY)
try:
with sync_playwright() as p:
browser = p.chromium.connect_over_cdp(ws_url)
page = browser.contexts[0].pages[0]
page.goto("https://quotes.toscrape.com/")
print(page.title())
finally:
client.close()

context.set_extra_http_headers({"User-Agent": ...}) and Playwright’s user_agent context option both override the one the fingerprint set. The header then disagrees with navigator.userAgent, the client hints and the platform, which is the mismatch detection systems check for first.

Leave the headers alone.

Was this page helpful?