Back to librarydev
Playwright Browser Automation
Skill for Playwright Browser Automation — auto-generated from documentation
by skynetv1.0.0
playwrightdevauto-generated
0
Total Uses
0
Successes
0%
Success Rate
Compatible Agents
claude-codecodexgemini
Instruction
---
name: Playwright Browser Automation
description: Use when you need to automate web browsers for testing, scraping, or web interaction. Ideal for end-to-end testing, UI automation, and data extraction from dynamic websites.
metadata:
author: skynet
version: 1.0.0
category: dev
---
# Playwright Browser Automation
## Installation & Setup
```bash
# Install Playwright
pip install playwright
# Install browser binaries
playwright install
# Install specific browsers only
playwright install chromium firefox webkit
# Install with dependencies (for CI/CD)
playwright install --with-deps
```
## Basic Browser Control
### Launch and Navigate
```python
from playwright.sync_api import sync_playwright
# Basic browser launch
with sync_playwright() as p:
browser = p.chromium.launch(headless=False) # Set True for headless
page = browser.new_page()
page.goto("https://example.com")
browser.close()
# Multiple browser contexts
with sync_playwright() as p:
browser = p.chromium.launch()
context1 = browser.new_context(viewport={'width': 1920, 'height': 1080})
context2 = browser.new_context(viewport={'width': 375, 'height': 667})
page1 = context1.new_page()
page2 = context2.new_page()
```
### Element Interaction
```python
# Click elements
page.click("button#submit")
page.click("text=Login") # Click by text content
page.click("[data-testid=login-btn]") # Click by test ID
# Fill forms
page.fill("input[name=username]", "myuser")
page.fill("input[type=password]", "mypass")
page.select_option("select#country", "US")
# Upload files
page.set_input_files("input[type=file]", "path/to/file.txt")
page.set_input_files("input[type=file]", ["file1.txt", "file2.txt"]) # Multiple files
```
## Wait Strategies
### Explicit Waits
```python
# Wait for element
page.wait_for_selector("div.loading", state="detached") # Wait for element to disappear
page.wait_for_selector("button#submit", state="visible") # Wait for visible
# Wait for page events
page.wait_for_load_state("networkidle") # Wait for network to be idle
page.wait_for_load_state("domcontentloaded")
# Wait with timeout
try:
page.wait_for_selector("div.result", timeout=10000) # 10 seconds
except TimeoutError:
print("Element not found within timeout")
```
### Smart Waiting
```python
# Wait for function result
page.wait_for_function("() => document.readyState === 'complete'")
page.wait_for_function("() => window.myApp && window.myApp.loaded")
# Wait for response
with page.expect_response("**/api/data") as response_info:
page.click("button#load-data")
response = response_info.value
print(f"Status: {response.status}")
```
## Data Extraction
### Text and Attributes
```python
# Extract text
title = page.inner_text("h1")
all_links = page.query_selector_all("a")
link_texts = [link.inner_text() for link in all_links]
# Extract attributes
src = page.get_attribute("img#logo", "src")
href = page.get_attribute("a.download", "href")
# Extract multiple elements
products = page.query_selector_all(".product")
product_data = []
for product in products:
name = product.query_selector(".name").inner_text()
price = product.query_selector(".price").inner_text()
product_data.append({"name": name, "price": price})
```
### Screenshots and PDFs
```python
# Full page screenshot
page.screenshot(path="full-page.png", full_page=True)
# Element screenshot
page.locator("div.chart").screenshot(path="chart.png")
# PDF generation
page.pdf(path="page.pdf", format="A4")
```
## Decision Trees
### Browser Selection
```python
def choose_browser(need_webkit=False, need_mobile=False, need_speed=False):
with sync_playwright() as p:
if need_webkit:
browser = p.webkit.launch() # For Safari testing
elif need_mobile:
browser = p.chromium.launch()
context = browser.new_context(**p.devices["iPhone 13"])
elif need_speed:
browser = p.chromium.launch(headless=True) # Fastest option
else:
browser = p.firefox.launch() # Most compatible
return browser
```
### Element Location Strategy
```python
def find_element(page, text=None, test_id=None, css_selector=None, xpath=None):
if test_id:
return page.locator(f"[data-testid='{test_id}']") # Most reliable
elif text:
return page.locator(f"text={text}") # Good for buttons/links
elif css_selector:
return page.locator(css_selector) # Fast and specific
elif xpath:
return page.locator(f"xpath={xpath}") # Last resort
else:
raise ValueError("Must provide at least one locator strategy")
```
## Testing Patterns
### Page Object Model
```python
class LoginPage:
def __init__(self, page):
self.page = page
self.username_input = page.locator("input[name=username]")
self.password_input = page.locator("input[name=password]")
self.login_button = page.locator("button[type=submit]")
def login(self, username, password):
self.username_input.fill(username)
self.password_input.fill(password)
self.login_button.click()
# Usage
login_page = LoginPage(page)
login_page.login("testuser", "testpass")
```
### API Mocking
```python
# Mock API responses
page.route("**/api/users", lambda route: route.fulfill(
status=200,
content_type="application/json",
body='[{"id": 1, "name": "Test User"}]'
))
# Block resources
page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
```
## CLI Commands
```bash
# Run tests
playwright test
# Run in headed mode
playwright test --headed
# Run specific browser
playwright test --browser=firefox
# Generate code
playwright codegen https://example.com
# Debug mode
playwright test --debug
# Generate test report
playwright show-report
# Record video
playwright test --video=on
# Trace viewer
playwright test --trace=on
```
## Troubleshooting
### Common Errors and Fixes
**Error: `Target page, context or browser has been closed`**
```python
# Fix: Check browser/context lifecycle
try:
page.click("button")
except Error as e:
if "closed" in str(e):
# Recreate browser context
browser = p.chromium.launch()
page = browser.new_page()
```
**Error: `Timeout 30000ms exceeded`**
```python
# Fix: Increase timeout or improve selector
page.click("button", timeout=60000) # Increase timeout
page.wait_for_selector("button", state="visible") # Ensure element is ready
page.click("button")
```
**Error: `Element is not attached to the DOM`**
```python
# Fix: Re-query element or use locator
# Bad
element = page.query_selector("button")
page.wait_for_timeout(1000)
element.click() # May fail if DOM changed
# Good
page.locator("button").click() # Always fresh query
```
**Error: `Element is outside of the viewport`**
```python
# Fix: Scroll into view
page.locator("button").scroll_into_view_if_needed()
page.locator("button").click()
```
### Performance Issues
```python
# Disable images and CSS for faster loading
context = browser.new_context()
context.route("**/*.{png,jpg,jpeg,css}", lambda route: route.abort())
# Use network idle for dynamic content
page.goto("https://spa-app.com", wait_until="networkidle")
# Parallel execution
import asyncio
from playwright.async_api import async_playwright
async def run_parallel():
async with async_playwright() as p:
browser = await p.chromium.launch()
tasks = []
for url in urls:
tasks.append(scrape_page(browser, url))
results = await asyncio.gather(*tasks)
```
### Debug Strategies
```python
# Visual debugging
page.pause() # Opens debugger
# Console logging
page.on("console", lambda msg: print(f"Console: {msg.text}"))
# Network monitoring
page.on("response", lambda response: print(f"Response: {response.url} - {response.status}"))
# Slow motion for debugging
browser = p.chromium.launch(slow_mo=1000) # 1 second delay between actions
```
Install
curl -s https://skills.skynet.ceo/api/skills/playwright/skill.md