--- name: node-playwright-web-automation description: Use Node.js Playwright for web automation on this system — the browser tool fails due to sandbox issues. --- # Node.js Playwright Web Automation On this server, `browser_navigate` and other browser tools fail with "No usable sandbox" errors. Use Node.js + Playwright directly instead. ## Environment - Playwright: `/home/ubuntu/.hermes/hermes-agent/node_modules/playwright` - Chromium: `/home/ubuntu/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome` - Node.js: available in PATH ## Usage Pattern 1. Write JS script to `/tmp/task.js` 2. Run: `cd /home/ubuntu && node /tmp/task.js` ## Script Template ```javascript const { chromium } = require("/home/ubuntu/.hermes/hermes-agent/node_modules/playwright"); (async () => { const browser = await chromium.launch({ headless: true, args: ["--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"] }); const context = await browser.newContext({ ignoreHTTPSErrors: true }); const page = await context.newPage(); try { await page.goto("https://example.com", { waitUntil: "domcontentloaded", timeout: 30000 }); await page.waitForTimeout(3000); // Fill inputs await page.fill('input[type="text"]', "value"); await page.fill('input[type="password"]', "password"); // Click login button await page.click(".btn-primary"); await page.waitForTimeout(5000); console.log("URL: " + page.url()); console.log("Title: " + await page.title()); const txt = await page.evaluate(() => document.body.innerText); console.log("Body: " + txt.substring(0, 1000)); } catch (e) { console.error("ERROR: " + e.message); } await browser.close(); })(); ``` ## Pitfalls - Use `ignoreHTTPSErrors: true` — atomlisting.com and other sites may have cert issues - Use `waitUntil: "domcontentloaded"` — `networkidle` often times out on SPA sites - `page.fill()` is more reliable than `input.click()` + `input.type()` - Login buttons may have spaces in text: "登 录" not "登录" - Write scripts to files and run them — inline `node -e` breaks on quotes - Always close browser at the end to prevent zombie processes