From bfe3e773a4c8bbccc5f4cab6e603f826d510d0cb Mon Sep 17 00:00:00 2001 From: ceki-plugin Date: Fri, 17 Jul 2026 06:52:48 +0000 Subject: [PATCH 1/3] docs: add Playwright/Puppeteer/Selenium compatibility section --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 67c62b4..11e28d6 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,16 @@ asyncio.run(main()) **BREAKING in 2.2.0:** `connect()` no longer accepts `relay_url=` or `reconnect=` kwargs — pass a `ConnectOptions` object instead. +## Playwright / Puppeteer / Selenium Compatibility + +Ceki speaks raw **CDP (Chrome DevTools Protocol)** — the same protocol Playwright and Puppeteer use internally. Most automation scripts port with minimal changes: + +- **Playwright** — `page.context.newCDPSession(page)` → `client.rent()`, then replace `cdp_session.send('DOM.getDocument')` with `browser.send({"method": "DOM.getDocument"})`. Navigation, clicking, typing, and DOM queries work identically. +- **Puppeteer** — `page._client().send('DOM.getDocument')` → `browser.send({"method": "DOM.getDocument"})`. Same CDP method names and params. +- **Selenium** — `driver.execute_cdp_cmd('DOM.getDocument', {})` → `browser.send({"method": "DOM.getDocument"})`. Same method names, same parameter shapes. + +The `browser.send({"method": ..., "params": ...})` method mirrors Playwright's `CDPSession.send()` — same method names, same parameter shapes. Most scripts need only import and connection changes. + ## Environment Variables | Variable | Description | From 8da91bb17b3c050576bd467f294739c9286fca06 Mon Sep 17 00:00:00 2001 From: iWedmak Om Date: Fri, 17 Jul 2026 06:59:13 +0000 Subject: [PATCH 2/3] =?UTF-8?q?feat(docs):=20expand=20compat=20section=20?= =?UTF-8?q?=E2=80=94=20comparison=20table,=20migration=20example,=20MCP,?= =?UTF-8?q?=20anti-detect=20tools=20-=20Add=20feature=20comparison=20table?= =?UTF-8?q?=20(residential=20IPs,=20human=20mimicry,=20captcha=20solving,?= =?UTF-8?q?=20MCP)=20-=20Add=20Playwright=20=E2=86=92=20Ceki=20side-by-sid?= =?UTF-8?q?e=20migration=20example=20(Python)=20-=20Add=20undetected-chrom?= =?UTF-8?q?edriver=20and=20selenium-wire=20migration=20notes=20-=20Add=20M?= =?UTF-8?q?CP=20section=20showing=20zero-code=20browser=20tools=20for=20AI?= =?UTF-8?q?=20agents=20-=20Add=20compatibility=20badge=20at=20top=20of=20R?= =?UTF-8?q?EADME?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11e28d6..d9679b0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # ceki-sdk +> **Using Playwright / Puppeteer / Selenium?** Ceki speaks the same CDP protocol — [see migration guide](#playwright--puppeteer--selenium-compatibility) + Python SDK for [browser.ceki.me](https://browser.ceki.me) — rent real browsers from real people for AI agent automation. ## Install @@ -30,13 +32,72 @@ asyncio.run(main()) ## Playwright / Puppeteer / Selenium Compatibility -Ceki speaks raw **CDP (Chrome DevTools Protocol)** — the same protocol Playwright and Puppeteer use internally. Most automation scripts port with minimal changes: +Ceki speaks raw **CDP (Chrome DevTools Protocol)** — the same protocol Playwright and Puppeteer use internally. Most automation scripts port with just an import and connection change. + +### Why Ceki instead of your current stack? + +| Feature | Playwright | Puppeteer | Selenium | **Ceki** | +|---|---|---|---|---| +| Real residential IPs | ❌ | ❌ | ❌ | ✅ | +| Human behavioral mimicry | ❌ | ❌ | ❌ | ✅ | +| Captcha solving via chat | ❌ | ❌ | ❌ | ✅ | +| Raw CDP access | ✅ | ✅ | Partial | ✅ native | +| MCP-native | ❌ | ❌ | ❌ | ✅ | +| Real human browser provider | ❌ | ❌ | ❌ | ✅ | +| Zero bot detection risk | ❌ | ❌ | ❌ | ✅ | + +### Per-framework migration - **Playwright** — `page.context.newCDPSession(page)` → `client.rent()`, then replace `cdp_session.send('DOM.getDocument')` with `browser.send({"method": "DOM.getDocument"})`. Navigation, clicking, typing, and DOM queries work identically. - **Puppeteer** — `page._client().send('DOM.getDocument')` → `browser.send({"method": "DOM.getDocument"})`. Same CDP method names and params. - **Selenium** — `driver.execute_cdp_cmd('DOM.getDocument', {})` → `browser.send({"method": "DOM.getDocument"})`. Same method names, same parameter shapes. +- **undetected-chromedriver** — больше не нужен. Ceki предоставляет реальный fingerprint браузера реального человека + резидентный IP. Никаких патчей WebDriver. +- **selenium-wire** — перехват запросов: `browser.send({"method": "Network.enable"})` + подписка на событие `Network.responseReceived`. +- **MCP** — Ceki is MCP-native. Connect it as an MCP server (`ceki mcp`), and any MCP client (Claude Code, Cline, Cursor) gets browser tools — navigate, click, type, screenshot, captcha chat — without writing a single line of CDP code. + +### Migration example: Playwright → Ceki (Python) + + + + +
Playwright (raw CDP)Ceki
+ +```python +from playwright.async_api import async_playwright + +async with async_playwright() as p: + browser = await p.chromium.launch() + page = await browser.new_page() + cdp = await page.context.new_cdp_session(page) + await cdp.send("Page.navigate", + {"url": "https://x.com"}) + await page.click("text=Log in") + data = await cdp.send( + "Page.captureScreenshot") + await browser.close() +``` + + + +```python +from ceki_sdk import connect + +async def main(): + client = await connect(API_KEY) + br = await client.rent(sid) + await br.send({ + "method": "Page.navigate", + "params": {"url": "https://x.com"}, + }) + await br.click(320, 480) + snap = await br.screenshot() + await br.close() + await client.close() +``` + +
-The `browser.send({"method": ..., "params": ...})` method mirrors Playwright's `CDPSession.send()` — same method names, same parameter shapes. Most scripts need only import and connection changes. +The `browser.send({"method": ..., "params": ...})` method mirrors Playwright's `CDPSession.send()` — same CDP method names, same parameter shapes. Only the connection setup changes. ## Environment Variables From 658d34498e3249ac4de9ad8275238a4adfa84fa7 Mon Sep 17 00:00:00 2001 From: iWedmak Om Date: Fri, 17 Jul 2026 07:15:32 +0000 Subject: [PATCH 3/3] Fix Russian text and add Known Differences section to compat docs --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d9679b0..184edfb 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,8 @@ Ceki speaks raw **CDP (Chrome DevTools Protocol)** — the same protocol Playwri - **Playwright** — `page.context.newCDPSession(page)` → `client.rent()`, then replace `cdp_session.send('DOM.getDocument')` with `browser.send({"method": "DOM.getDocument"})`. Navigation, clicking, typing, and DOM queries work identically. - **Puppeteer** — `page._client().send('DOM.getDocument')` → `browser.send({"method": "DOM.getDocument"})`. Same CDP method names and params. - **Selenium** — `driver.execute_cdp_cmd('DOM.getDocument', {})` → `browser.send({"method": "DOM.getDocument"})`. Same method names, same parameter shapes. -- **undetected-chromedriver** — больше не нужен. Ceki предоставляет реальный fingerprint браузера реального человека + резидентный IP. Никаких патчей WebDriver. -- **selenium-wire** — перехват запросов: `browser.send({"method": "Network.enable"})` + подписка на событие `Network.responseReceived`. +- **undetected-chromedriver** — no longer needed. Ceki provides a real human browser fingerprint + residential IP. No WebDriver patches required. +- **selenium-wire** — request interception: `browser.send({"method": "Network.enable"})` + subscribe to `Network.responseReceived` events. - **MCP** — Ceki is MCP-native. Connect it as an MCP server (`ceki mcp`), and any MCP client (Claude Code, Cline, Cursor) gets browser tools — navigate, click, type, screenshot, captcha chat — without writing a single line of CDP code. ### Migration example: Playwright → Ceki (Python) @@ -99,6 +99,15 @@ async def main(): The `browser.send({"method": ..., "params": ...})` method mirrors Playwright's `CDPSession.send()` — same CDP method names, same parameter shapes. Only the connection setup changes. +### Known Differences + +Ceki's CDP-over-WSS relay is not a direct local CDP pipe — a few differences to keep in mind when migrating from Playwright / Puppeteer / Selenium: + +- **No CSS selectors on interaction methods** — `click`, `type`, and `scroll` take viewport coordinates, not CSS selectors. For element-based selection, use `Runtime.evaluate` to get bounding rects, then pass coordinates. +- **Speed** — each command travels over the WebSocket relay with ~50–200ms round-trip (internet-latency dependent, unlike local CDP which is sub-millisecond). Batch operations in a single `Runtime.evaluate` where possible, rather than chaining many small CDP calls. +- **120s grace window** — after each command there's a 120s window before the session auto-closes. This is by design for workflow chaining, but long-running idle sessions will need a keepalive. +- **Runtime.evaluate serialization** — CDP's `Runtime.evaluate` returns JSON-serializable values only. Functions, symbols, DOM nodes, and circular references are not transferable. Use `--returnByValue` explicitly. + ## Environment Variables | Variable | Description |