Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Playwright Browser Automation

v2.0.0

Browser automation using Playwright API directly. Navigate websites, interact with elements, extract data, take screenshots, generate PDFs, record videos, and automate complex workflows. More reliable than MCP approach.

9· 7.4k·54 current·60 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for spiceman161/playwright-browser-automation.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Playwright Browser Automation" (spiceman161/playwright-browser-automation) from ClawHub.
Skill page: https://clawhub.ai/spiceman161/playwright-browser-automation
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Required binaries: node, npx
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Canonical install target

openclaw skills install spiceman161/playwright-browser-automation

ClawHub CLI

Package manager switcher

npx clawhub@latest install playwright-browser-automation
Security Scan
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
medium confidence
!
Purpose & Capability
The skill claims to provide direct Playwright API automation (and explicitly says it's 'more reliable than MCP'), but the bundled examples.py demonstrates using a Playwright MCP server and MCP tool calls. This contradiction could be innocent (leftover example) or indicate mixed/unclear design — the presence of MCP-related examples is not coherent with the stated single-purpose description.
Instruction Scope
SKILL.md contains standard Playwright usage and install instructions only. It instructs installing browsers (npx playwright install ...) and running code that will read/write local files (storageState auth.json, screenshots, videos, downloads, uploads) and may require sudo for system deps. It does not instruct reading arbitrary system secrets or contacting unexpected external endpoints, but the examples include hard-coded credential examples and file paths which imply read/write filesystem access.
Install Mechanism
Install uses the official npm package 'playwright' and recommends npx playwright install for browser binaries — this is a common and expected install path. Note: browser binaries (~100MB each) will be downloaded and native dependencies may require elevated privileges on some systems.
Credentials
The skill declares no required environment variables or credentials (proportionate). However, examples show usage of credentials (HTTP basic auth, cookies, storageState) and file paths for uploads/downloads; those imply the skill will access local filesystem and could hold secrets in files if used. No unrelated credentials are requested.
Persistence & Privilege
The skill does not request always:true and doesn't modify other skills or global agent settings. It runs as a normal, user-invocable skill. Installation steps may require sudo for system dependencies, but runtime privileges are not elevated by the skill itself.
What to consider before installing
This skill appears to be an ordinary Playwright automation helper, but there are a few things to check before installing: - Confirm intent: the skill description promises direct Playwright API usage but the included Python example uses an MCP server. Ask the publisher which mode is intended (direct API vs MCP) — mixed examples can hide unexpected behavior. - Installation will download sizable browser binaries (chromium/firefox/webkit) and may require sudo for system deps; plan for disk and privileged-install implications. - The skill will read/write files (screenshots, videos, downloads, storageState/auth.json). Do not point it to sensitive filesystem locations or store secrets in plain files unless you trust the skill. - Examples show credentials (username/password) in snippets. Treat those as placeholders; never paste real secrets into examples. If you plan to automate authenticated sites, consider using temporary/test credentials and review how auth state files are stored. - Source is unknown: verify the npm 'playwright' package origin and the skill publisher before granting network/filesystem access. If you need stronger assurance, run the install and execution in a sandboxed environment first or require the publisher to clarify the MCP vs direct-API inconsistency.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

🎭 Clawdis
OSLinux · macOS · Windows
Binsnode, npx
latestvk97d7empycz9yke3jfdrfm9rxx80rd3a
7.4kdownloads
9stars
1versions
Updated 20h ago
v2.0.0
MIT-0
Linux, macOS, Windows

Playwright Browser Automation

Direct Playwright API for reliable browser automation without MCP complexity.

Installation

# Install Playwright
npm install -g playwright

# Install browsers (one-time, ~100MB each)
npx playwright install chromium
# Optional:
npx playwright install firefox
npx playwright install webkit

# For system dependencies on Ubuntu/Debian:
sudo npx playwright install-deps chromium

Quick Start

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({ headless: true });
  const page = await browser.newPage();
  
  await page.goto('https://example.com');
  await page.screenshot({ path: 'screenshot.png' });
  
  await browser.close();
})();

Best Practices

1. Use Locators (Auto-waiting)

// ✅ GOOD: Uses auto-waiting and retries
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByLabel('Username').fill('user');
await page.getByPlaceholder('Search').fill('query');

// ❌ BAD: May fail if element not ready
await page.click('#submit');

2. Prefer User-Facing Attributes

// ✅ GOOD: Resilient to DOM changes
await page.getByRole('heading', { name: 'Welcome' });
await page.getByText('Sign in');
await page.getByTestId('login-button');

// ❌ BAD: Brittle CSS selectors
await page.click('.btn-primary > div:nth-child(2)');

3. Handle Dynamic Content

// Wait for network idle
await page.goto('https://spa-app.com', { waitUntil: 'networkidle' });

// Wait for specific element
await page.waitForSelector('.results-loaded');
await page.waitForFunction(() => document.querySelectorAll('.item').length > 0);

4. Use Contexts for Isolation

// Each context = isolated session (cookies, storage)
const context = await browser.newContext();
const page = await context.newPage();

// Multiple pages in one context
const page2 = await context.newPage();

5. Network Interception

// Mock API responses
await page.route('**/api/users', route => {
  route.fulfill({
    status: 200,
    body: JSON.stringify({ users: [] })
  });
});

// Block resources
await page.route('**/*.{png,jpg,css}', route => route.abort());

Common Patterns

Form Automation

// Fill form
await page.goto('https://example.com/login');
await page.getByLabel('Username').fill('myuser');
await page.getByLabel('Password').fill('mypass');
await page.getByRole('button', { name: 'Sign in' }).click();

// Wait for navigation/result
await page.waitForURL('/dashboard');
await expect(page.getByText('Welcome')).toBeVisible();

Data Extraction

// Extract table data
const rows = await page.$$eval('table tr', rows =>
  rows.map(row => ({
    name: row.querySelector('td:nth-child(1)')?.textContent,
    price: row.querySelector('td:nth-child(2)')?.textContent
  }))
);

// Extract with JavaScript evaluation
const data = await page.evaluate(() => {
  return Array.from(document.querySelectorAll('.product')).map(p => ({
    title: p.querySelector('.title')?.textContent,
    price: p.querySelector('.price')?.textContent
  }));
});

Screenshots & PDFs

// Full page screenshot
await page.screenshot({ path: 'full.png', fullPage: true });

// Element screenshot
await page.locator('.chart').screenshot({ path: 'chart.png' });

// PDF (Chromium only)
await page.pdf({ 
  path: 'page.pdf', 
  format: 'A4',
  printBackground: true 
});

Video Recording

const context = await browser.newContext({
  recordVideo: {
    dir: './videos/',
    size: { width: 1920, height: 1080 }
  }
});
const page = await context.newPage();

// ... do stuff ...

await context.close(); // Video saved automatically

Mobile Emulation

const context = await browser.newContext({
  viewport: { width: 375, height: 667 },
  userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0)',
  isMobile: true,
  hasTouch: true
});

Authentication

// Method 1: HTTP Basic Auth
const context = await browser.newContext({
  httpCredentials: { username: 'user', password: 'pass' }
});

// Method 2: Cookies
await context.addCookies([
  { name: 'session', value: 'abc123', domain: '.example.com', path: '/' }
]);

// Method 3: Local Storage
await page.evaluate(() => {
  localStorage.setItem('token', 'xyz');
});

// Method 4: Reuse auth state
await context.storageState({ path: 'auth.json' });
// Later: await browser.newContext({ storageState: 'auth.json' });

Advanced Features

File Upload/Download

// Upload
await page.setInputFiles('input[type="file"]', '/path/to/file.pdf');

// Download
const [download] = await Promise.all([
  page.waitForEvent('download'),
  page.click('a[download]')
]);
await download.saveAs('/path/to/save/' + download.suggestedFilename());

Dialogs Handling

page.on('dialog', dialog => {
  if (dialog.type() === 'alert') dialog.accept();
  if (dialog.type() === 'confirm') dialog.accept();
  if (dialog.type() === 'prompt') dialog.accept('My answer');
});

Frames & Shadow DOM

// Frame by name
const frame = page.frame('frame-name');
await frame.click('button');

// Frame by locator
const frame = page.frameLocator('iframe').first();
await frame.getByRole('button').click();

// Shadow DOM
await page.locator('my-component').locator('button').click();

Tracing (Debug)

await context.tracing.start({ screenshots: true, snapshots: true });

// ... run tests ...

await context.tracing.stop({ path: 'trace.zip' });
// View at https://trace.playwright.dev

Configuration Options

const browser = await chromium.launch({
  headless: true,        // Run without UI
  slowMo: 50,           // Slow down by 50ms (for debugging)
  devtools: false,      // Open DevTools
  args: ['--no-sandbox', '--disable-setuid-sandbox'] // Docker/Ubuntu
});

const context = await browser.newContext({
  viewport: { width: 1920, height: 1080 },
  locale: 'ru-RU',
  timezoneId: 'Europe/Moscow',
  geolocation: { latitude: 55.7558, longitude: 37.6173 },
  permissions: ['geolocation'],
  userAgent: 'Custom Agent',
  bypassCSP: true,      // Bypass Content Security Policy
});

Error Handling

// Retry with timeout
try {
  await page.getByRole('button', { name: 'Load' }).click({ timeout: 10000 });
} catch (e) {
  console.log('Button not found or not clickable');
}

// Check if element exists
const hasButton = await page.getByRole('button').count() > 0;

// Wait with custom condition
await page.waitForFunction(() => 
  document.querySelectorAll('.loaded').length >= 10
);

Sudoers Setup

For Playwright browser installation:

# /etc/sudoers.d/playwright
username ALL=(root) NOPASSWD: /usr/bin/npx playwright install-deps *
username ALL=(root) NOPASSWD: /usr/bin/npx playwright install *

References

Comments

Loading comments...