Install
$ agentstack add skill-mauromedda-agent-toolkit-web-automation ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ABOUTME: Claude Code skill for web automation, debugging, and E2E testing using Playwright
ABOUTME: Covers interactive automation, passive monitoring, screenshots, and security verification
Web Automation with Playwright
Browser automation and debugging using Playwright in Python or JavaScript/TypeScript.
Detailed patterns: See references/python-patterns.md and references/javascript-patterns.md
Quick Reference
| Task | Helper Script | |------|---------------| | Login / fill forms | examples/python/form_interaction.py | | Take screenshots | examples/python/screenshot_capture.py | | Handle cookie consent | scripts/cookie_consent.py | | Discover page elements | examples/python/element_discovery.py | | Capture network traffic | scripts/network_inspector.py | | Debug console errors | scripts/console_debugger.py | | Full debug (network+console) | scripts/combined_debugger.py | | Compare websites visually | examples/python/visual_compare.py |
Always run helpers first:
uv run ~/.claude/skills/web-automation/examples/python/element_discovery.py http://localhost:3000
uv run ~/.claude/skills/web-automation/examples/python/screenshot_capture.py http://localhost:3000 --output /tmp/shots
Modes of Operation
| Mode | When to Use | Example | |------|-------------|---------| | Interactive | Click, type, navigate | Login flow, form submission | | Passive | Observe only | Network capture, console monitoring | | E2E Testing | Automated test suites | Playwright Test framework |
When to Invoke (Proactive)
- Verifying UI fixes - After changing frontend code
- Testing form fields/dropdowns - Verify correct values display
- Confirming visual changes - Take screenshots
- Reproducing bugs - Automate steps to reproduce
- Security verification - After Gemini/static analysis finds issues
🔄 RESUMED SESSION CHECKPOINT
┌─────────────────────────────────────────────────────────────┐
│ SESSION RESUMED - WEB AUTOMATION VERIFICATION │
│ │
│ 1. Was I in the middle of browser automation? │
│ → Run: ps aux | grep -E "chromium|playwright|node" │
│ │
│ 2. Were there UI verification tasks pending? │
│ → Check summary for "verify", "test UI", "screenshot" │
│ │
│ 3. Did previous automation capture any findings? │
│ → Check /tmp/ for screenshots, debug outputs │
└─────────────────────────────────────────────────────────────┘
Decision Flow
Task:
+-- Need to interact? (click, type, submit) → Interactive mode
+-- Just observe/capture? → Passive mode (combined_debugger.py)
+-- Security verification? → Passive mode + grep for sensitive patterns
CRITICAL: Handling Overlays
Overlays WILL block automation. Always dismiss after page.goto():
Python (Quick Pattern)
page.goto('https://example.com')
page.wait_for_load_state('networkidle')
# Dismiss cookie consent
for sel in ['button:has-text("Accept all")', '[class*="cookie"] button[class*="accept"]']:
try:
btn = page.locator(sel).first
if btn.is_visible(timeout=2000):
btn.click()
break
except:
continue
Nuclear Option (Remove All Overlays)
page.evaluate('''() => {
const patterns = ['cookie', 'consent', 'modal', 'overlay', 'popup', 'backdrop'];
for (const p of patterns) {
document.querySelectorAll(`[class*="${p}"], [id*="${p}"]`).forEach(el => {
if (getComputedStyle(el).position === 'fixed') el.remove();
});
}
document.body.style.overflow = 'auto';
}''')
Full implementation: See references/python-patterns.md
Core Patterns
Python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('http://localhost:3000')
page.wait_for_load_state('networkidle') # CRITICAL
# ... automation
browser.close()
JavaScript
import { test, expect } from '@playwright/test';
test('example', async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('networkidle');
await expect(page.locator('.element')).toBeVisible();
});
Common Operations
| Operation | Python | JavaScript | |-----------|--------|------------| | Screenshot | page.screenshot(path='/tmp/s.png') | await page.screenshot({ path: '/tmp/s.png' }) | | Full page | page.screenshot(path='/tmp/s.png', full_page=True) | await page.screenshot({ path: '/tmp/s.png', fullPage: true }) | | Fill input | page.fill('input[name="email"]', 'x@y.com') | await page.fill('input[name="email"]', 'x@y.com') | | Select dropdown | page.select_option('select#id', 'value') | await page.selectOption('select#id', 'value') | | Click | page.click('button[type="submit"]') | await page.click('button[type="submit"]') | | Wait network | page.wait_for_load_state('networkidle') | await page.waitForLoadState('networkidle') | | Wait element | page.wait_for_selector('.result') | await page.waitForSelector('.result') |
Selector Strategies (Order of Preference)
- Role-based:
page.get_by_role('button', name='Submit') - Text-based:
page.get_by_text('Click me') - Test IDs:
page.get_by_test_id('submit-btn') - CSS:
page.locator('.btn-primary') - XPath (last resort):
page.locator('//button[@type="submit"]')
Verification Checklist
| What to Verify | Approach | |----------------|----------| | Dropdown value | page.locator('select').input_value() | | Input text | page.locator('input').input_value() | | Element visible | page.locator('.element').is_visible() | | Text content | page.locator('.element').text_content() | | Page URL | page.url after action |
Passive Debugging Scripts
| Script | Purpose | Example | |--------|---------|---------| | combined_debugger.py | Network + Console + Errors | uv run ... --duration 30 --output /tmp/debug.json | | network_inspector.py | Network only | uv run ... --errors-only | | console_debugger.py | Console/errors only | uv run ... --with-stack-traces |
Security Verification
# After Gemini found sensitive data logging
uv run ~/.claude/skills/web-automation/scripts/console_debugger.py \
http://localhost:3000 --duration 60 --output /tmp/security.json
grep -i "password\|token\|secret\|bearer" /tmp/security.json
Visual Comparison
NEVER say "I cannot visually browse". Instead:
# Compare two sites
uv run ~/.claude/skills/web-automation/examples/python/visual_compare.py \
https://reference-site.com \
http://localhost:3000 \
--output /tmp/compare
# Then read the screenshots using Read tool
Language Selection
| Use Case | Recommended | Reason | |----------|-------------|--------| | Existing JS/TS project | JavaScript | Consistent tooling | | Existing Python project | Python | Consistent tooling | | Quick scripts | Python | Simpler setup with uv run | | Test suites | JavaScript | Better @playwright/test framework |
Test Framework Integration
See references/test-framework.md for:
- Unified test runner (
test_utils.py) - Server auto-detection and startup
- Framework detection (Playwright, Jest, pytest, etc.)
# Detect and run tests with server
uv run ~/.claude/skills/web-automation/scripts/test_utils.py . --run --with-server
Common Pitfalls
| Pitfall | Solution | |---------|----------| | Overlay blocking clicks | Call overlay dismissal after EVERY page load | | DOM inspection before JS loads | Always wait_for_load_state('networkidle') first | | Headful browser in CI | Always use headless: true | | Flaky selectors | Prefer role/text selectors over CSS classes | | Race conditions | Use explicit waits, not wait_for_timeout |
Prerequisites
Python
Scripts include inline dependencies (PEP 723); uv run auto-installs them.
JavaScript
npm init -y
npm install -D @playwright/test
npx playwright install chromium
Running E2E Tests
JavaScript
npx playwright test # Run all
npx playwright test --ui # UI mode
npx playwright test --headed # See browser
Python
pip install pytest-playwright
pytest tests/
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mauromedda
- Source: mauromedda/agent-toolkit
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.