Koko-only SDK APIs live behind the LP.* CDP namespace — designed for AI agents and high-density crawling where Playwright's DOM queries are too verbose or fragile.
Token-efficient extraction
const md = await page.markdown();
const tree = await page.semanticTree({ format: "text", maxDepth: 4 });
const meta = await page.getStructuredData();
const forms = await page.detectForms();
const links = await page.links();
NodeHandle (stable backend nodes)
Semantic tree and form detection return backendNodeId handles — more stable than CSS for agent loops.
const [search] = await page.findElement({ role: "combobox", name: "search" });
const input = page.node(search.backendNodeId!);
await input.fill("Koko browser");
const submit = await page.waitForSelectorHandle('input[name="btnK"]');
await submit.click();
NodeHandle actions
| Method | CDP backing |
|---|---|
fill(text) | LP.fillNode |
click() | LP.clickNode ⚠️ hang risk on some buttons |
hover() | LP.hoverNode |
press(key) | LP.pressKey |
selectOption(v) | LP.selectOptionNode |
check() / uncheck() | LP.setCheckedNode |
Google SERP workflow
const serp = await page.searchGoogle({
query: "zig language tutorial",
limit: 5,
});
console.log(serp.results); // { title, url }[]
// Includes TTFX probe, block detection (/sorry, captcha), pathHint diagnostics
Session persistence
import { captureSessionState, restoreSessionState } from "koko-sdk";
const state = await captureSessionState(page, "https://example.com");
await restoreSessionState(page, state);
JavaScript dialogs
Pre-arm dialogs before triggering JS — headless auto-dismiss breaks reactive CDP:
await page.armDialog({ accept: true, promptText: "hello" });
await page.evaluate("prompt('Name?')");
Crawl extract
const result = await page.extract();
// TTFX probe + structured extract optimized for crawlers