Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Run Node.js scripts using Playwright for full browser automation, including scraping, screenshots, form handling, and dynamic content interaction.
Run Node.js scripts using Playwright for full browser automation, including scraping, screenshots, form handling, and dynamic content interaction.
This item appears to require sign-in or permission before the package can be fetched. Open the source page and confirm access manually.
Use the source page and any available docs to guide the install because the item requires authentication or permission before the package can be fetched.
I tried to install a skill package from Yavira, but the item requires authentication or permission before the package can be fetched. Inspect the source page and any extracted docs, then tell me what you can confirm and any manual steps still required.
I tried to upgrade a skill package from Yavira, but the item requires authentication or permission before the package can be fetched. Compare the source page and any extracted docs with my current installation, then summarize what changed and what manual follow-up I still need.
๐ค Developed together by Kuba + Mahone ยท Feb 2026 Code-first browser automation with Playwright.
ToolUse Whenweb_fetchSimple pages, no JavaScript neededThis skillJavaScript-heavy sites, complex interactions, full controlstealth-browserBot detection / Cloudflare issuesbrowser toolVisual exploration, last resortplaywright-cliInteractive CLI without writing code
# One-time per project npm init -y npm install playwright npx playwright install chromium package.json example: { "name": "my-automation", "type": "module", "dependencies": { "playwright": "^1.40.0" } }
// tmp/example.mjs import { chromium } from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); console.log('Title:', await page.title()); await browser.close(); node tmp/example.mjs
import { chromium } from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.setViewportSize({ width: 1280, height: 800 }); await page.goto('https://example.com'); await page.screenshot({ path: 'tmp/screenshot.png', fullPage: true }); await browser.close();
import { chromium } from 'playwright'; const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://news.ycombinator.com'); const stories = await page.$$eval('.titleline > a', links => links.slice(0, 5).map(a => ({ title: a.innerText, url: a.href })) ); console.log(JSON.stringify(stories, null, 2)); await browser.close();
await page.goto('https://example.com/login'); await page.fill('input[name="email"]', 'user@example.com'); await page.fill('input[name="password"]', 'password'); await page.click('button[type="submit"]');
// Wait for network idle (SPA) await page.goto(url, { waitUntil: 'networkidle' }); // Wait for specific element await page.waitForSelector('.results', { timeout: 10000 }); // Wait for condition await page.waitForFunction(() => document.querySelectorAll('.item').length > 0 );
import fs from 'fs'; const SESSION_FILE = 'tmp/session.json'; let context; if (fs.existsSync(SESSION_FILE)) { context = await browser.newContext({ storageState: SESSION_FILE }); } else { context = await browser.newContext(); } const page = await context.newPage(); // ... login ... await context.storageState({ path: SESSION_FILE });
// Headless (default, fastest) await chromium.launch({ headless: true }); // Headed (see the browser) await chromium.launch({ headless: false }); // Slow motion (debugging) await chromium.launch({ headless: false, slowMo: 100 });
// CSS await page.click('button.submit'); await page.fill('input#email', 'text'); // Text content await page.click('text=Submit'); await page.click('text=/log\s*in/i'); // regex // XPath await page.click('xpath=//button[@type="submit"]'); // ARIA role await page.click('role=button[name="Submit"]'); // Test ID (most stable) await page.click('[data-testid="submit-btn"]'); // Chain selectors await page.click('nav >> text=Settings'); See references/selectors.md for complete selector guide.
try { await page.goto('https://example.com', { timeout: 30000 }); const hasResults = await page.locator('.results').isVisible().catch(() => false); if (!hasResults) { console.log('No results'); process.exit(0); } } catch (error) { console.error('Error:', error.message); await page.screenshot({ path: 'tmp/error.png' }); process.exit(1); } finally { await browser.close(); }
examples/screenshot.mjs - Full-page screenshots examples/scrape.mjs - Data extraction examples/form-interaction.mjs - Form automation examples/login-session.mjs - Persistent sessions
scripts/minimal-template.mjs - Clean starting point scripts/screenshot-template.mjs - Configurable screenshot scripts/scrape-template.mjs - Data scraping scaffold Copy templates: cp scripts/minimal-template.mjs tmp/my-task.mjs # Edit tmp/my-task.mjs, then run: node tmp/my-task.mjs
# Record interactions to generate code npx playwright codegen https://example.com # Debug selectors npx playwright codegen --target javascript https://example.com # Show trace npx playwright show-trace tmp/trace.zip
references/selectors.md - Complete selector guide (CSS, text, XPath, ARIA, test-id) references/debugging.md - Debugging techniques (headless, slowMo, screenshots) references/troubleshooting.md - Common errors and solutions
Always put scripts in tmp/ โ it's gitignored Use .mjs extension for ES modules (no type: module needed) Add console.log() liberally for debugging Use page.screenshot() when things go wrong For complex sites, add await page.waitForLoadState('networkidle') See references/debugging.md for detailed debugging guide See references/troubleshooting.md for common issues
Code helpers, APIs, CLIs, browser automation, testing, and developer operations.
Largest current source with strong distribution and engagement signals.