How to Automate Form Submissions Using Playwright
Playwright is a powerful web automation library that enables you to interact with forms programmatically. This guide covers form automation in both Python and JavaScript with practical examples and best practices.
Installation
Python Setup
pip install playwright
playwright install
JavaScript/Node.js Setup
npm install playwright
# Browser binaries are downloaded automatically
Basic Form Automation
Python Example
from playwright.sync_api import sync_playwright
def submit_form(playwright):
browser = playwright.chromium.launch(headless=False) # Set to True for production
page = browser.new_page()
try:
# Navigate to the form page
page.goto('https://example.com/login')
# Wait for form to load
page.wait_for_selector('form')
# Fill form fields
page.fill('input[name="username"]', 'your_username')
page.fill('input[name="password"]', 'your_password')
# Submit the form
page.click('button[type="submit"]')
# Wait for navigation after form submission
page.wait_for_url('**/dashboard**') # Wait for redirect to dashboard
print("Form submitted successfully!")
except Exception as e:
print(f"Error: {e}")
finally:
browser.close()
with sync_playwright() as p:
submit_form(p)
JavaScript Example
const { chromium } = require('playwright');
async function submitForm() {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
try {
// Navigate to the form page
await page.goto('https://example.com/login');
// Wait for form to load
await page.waitForSelector('form');
// Fill form fields
await page.fill('input[name="username"]', 'your_username');
await page.fill('input[name="password"]', 'your_password');
// Submit the form
await page.click('button[type="submit"]');
// Wait for navigation after form submission
await page.waitForURL('**/dashboard**');
console.log('Form submitted successfully!');
} catch (error) {
console.error('Error:', error);
} finally {
await browser.close();
}
}
submitForm();
Advanced Form Interactions
Handling Different Input Types
# Text inputs
page.fill('input[name="email"]', 'user@example.com')
# Checkboxes
page.check('input[name="terms"]') # Check
page.uncheck('input[name="newsletter"]') # Uncheck
# Radio buttons
page.check('input[value="option1"]')
# Select dropdowns
page.select_option('select[name="country"]', 'US')
# File uploads
page.set_input_files('input[type="file"]', 'path/to/file.pdf')
# Textareas
page.fill('textarea[name="message"]', 'Your message here')
Multiple Submission Methods
# Method 1: Click submit button
page.click('button[type="submit"]')
# Method 2: Press Enter on form field
page.press('input[name="username"]', 'Enter')
# Method 3: Call form.submit() with JavaScript
page.evaluate('document.querySelector("form").submit()')
# Method 4: Use page.submit_form() if form has action attribute
page.locator('form').submit()
Error Handling and Validation
Robust Form Submission
from playwright.sync_api import sync_playwright, TimeoutError
def robust_form_submit(playwright):
browser = playwright.chromium.launch()
page = browser.new_page()
try:
page.goto('https://example.com/contact', timeout=30000)
# Check if form exists
if not page.locator('form').is_visible():
raise Exception("Form not found on page")
# Fill required fields with validation
required_fields = {
'input[name="name"]': 'John Doe',
'input[name="email"]': 'john@example.com',
'textarea[name="message"]': 'Hello world'
}
for selector, value in required_fields.items():
if page.locator(selector).is_visible():
page.fill(selector, value)
else:
print(f"Warning: Field {selector} not found")
# Submit with confirmation
with page.expect_navigation():
page.click('button[type="submit"]')
# Check for success message or error
if page.locator('.success-message').is_visible():
print("Form submitted successfully!")
elif page.locator('.error-message').is_visible():
error_text = page.locator('.error-message').text_content()
print(f"Submission failed: {error_text}")
except TimeoutError:
print("Page load timeout")
except Exception as e:
print(f"Error: {e}")
finally:
browser.close()
with sync_playwright() as p:
robust_form_submit(p)
Waiting Strategies
# Wait for element to be visible
page.wait_for_selector('form', state='visible')
# Wait for form submission to complete
page.wait_for_load_state('networkidle')
# Wait for specific response
with page.expect_response('**/api/submit**') as response_info:
page.click('button[type="submit"]')
response = response_info.value
print(f"Status: {response.status}")
# Wait for URL change
page.wait_for_url('**/success**')
Best Practices
- Always use proper selectors: Prefer
data-testid
attributes over fragile CSS selectors - Handle timeouts: Set appropriate timeout values for slow-loading forms
- Validate before submission: Check if required fields are filled
- Wait for responses: Ensure form submission completes before proceeding
- Handle errors gracefully: Implement proper error handling and logging
- Respect rate limits: Add delays between multiple form submissions
- Use headless mode in production: Set
headless=True
for automated environments
Common Troubleshooting
- Element not found: Use
page.wait_for_selector()
before interacting - Form not submitting: Check if JavaScript validation is preventing submission
- Slow responses: Increase timeout values or wait for network idle state
- CAPTCHA protection: Some forms may require human verification
- CSRF tokens: Modern forms may need token handling for security
Responsible Usage
When automating form submissions: - Respect website terms of service - Implement reasonable delays between requests - Handle failures gracefully without overwhelming servers - Consider using official APIs when available - Test thoroughly before production deployment
Remember that automated form submission should be used responsibly and in compliance with website policies and applicable laws.