// Evaluate an expression in a headless Chrome (CDP) page and print the result. // Usage: node cdp-eval.mjs [waitMs] import { spawn } from 'node:child_process'; import fs from 'node:fs'; const [url, expr, waitMs = '6000'] = process.argv.slice(2); const PORT = 9333 + Math.floor(Math.random() * 200); const CHROME = 'C:/Program Files/Google/Chrome/Application/chrome.exe'; const udd = 'C:/Users/BRIAN~1.FER/AppData/Local/Temp/cdp-eval-' + process.pid + '-' + Date.now(); const chrome = spawn(CHROME, [ '--headless', `--remote-debugging-port=${PORT}`, `--user-data-dir=${udd}`, '--no-first-run', '--disable-gpu', '--enable-unsafe-swiftshader', 'about:blank', ], { stdio: 'ignore' }); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); try { let v; for (let i = 0; i < 100; i++) { try { v = await (await fetch(`http://127.0.0.1:${PORT}/json/version`)).json(); break; } catch { await sleep(200); } } if (!v) throw new Error('CDP never came up'); let t; try { t = await (await fetch(`http://127.0.0.1:${PORT}/json/new?${encodeURIComponent(url)}`, { method: 'PUT' })).json(); } catch { t = await (await fetch(`http://127.0.0.1:${PORT}/json/new?${encodeURIComponent(url)}`, { method: 'POST' })).json(); } const ws = new WebSocket(t.webSocketDebuggerUrl); let id = 0; const p = new Map(); const send = (m, pa = {}) => new Promise((res, rej) => { const i = ++id; p.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, method: m, params: pa })); }); ws.onmessage = (m) => { const x = JSON.parse(m.data); if (x.id && p.has(x.id)) { const { res, rej } = p.get(x.id); p.delete(x.id); x.error ? rej(new Error(x.error.message)) : res(x.result); } }; await new Promise((r) => (ws.onopen = r)); await send('Runtime.enable'); await sleep(Number(waitMs)); const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); if (r.exceptionDetails) throw new Error(JSON.stringify(r.exceptionDetails).slice(0, 400)); console.log(typeof r.result.value === 'object' ? JSON.stringify(r.result.value) : r.result.value); ws.close(); } finally { chrome.kill(); setTimeout(() => fs.rmSync(udd, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }), 1500); }