| name | web-form-automation |
| description | Automate web form interactions including login, file upload, text input, and form submission using Playwright. Use when user needs to automate website interactions, upload files to web forms, fill out forms with text input, click buttons, or submit data to web applications. Supports session management via cookies, compressed image uploads (webp), and proper event triggering for reliable form submission. |
Web Form Automation
Automate web form interactions reliably using Playwright with best practices for session management, file uploads, and form submission.
Quick Start
const { chromium } = require('playwright');
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com/form');
await page.locator('input[type="file"]').setInputFiles('/path/to/image.webp');
await page.locator('textarea').pressSequentially('Your text', { delay: 30 });
await page.locator('button[type="submit"]').click({ force: true });
Session Management
Using Browser Session Data
When user provides a JSON file with session data:
const sessionData = JSON.parse(fs.readFileSync('session.json', 'utf8'));
for (const cookie of sessionData.cookies || []) {
await context.addCookies([cookie]);
}
await page.evaluate((data) => {
for (const [k, v] of Object.entries(data.localStorage || {})) {
localStorage.setItem(k, v);
}
}, sessionData);
File Upload Best Practices
Image Compression
Always compress images before upload for reliability:
convert input.png output.webp
convert input.png -resize 1024x1024 output.webp
Size comparison:
- Original PNG: ~4MB
- Compressed PNG: ~1MB
- WebP: ~30-50KB (99% smaller)
Upload Sequence
const fileInputs = await page.locator('input[type="file"]').all();
await fileInputs[0].setInputFiles('/path/to/start.webp');
await page.waitForTimeout(3000);
await fileInputs[1].setInputFiles('/path/to/end.webp');
await page.waitForTimeout(3000);
Text Input Best Practices
Use pressSequentially, not fill()
❌ Don't use fill() - doesn't trigger input events:
await textInput.fill('text');
✅ Use pressSequentially() - simulates real typing:
await textInput.pressSequentially('text', { delay: 30 });
Trigger Events Manually (if needed)
await page.evaluate(() => {
const el = document.querySelector('textarea');
el.dispatchEvent(new Event('input', { bubbles: true }));
el.dispatchEvent(new Event('change', { bubbles: true }));
});
Button Clicking
Force Click When Disabled
If button appears disabled but should be clickable:
await button.click({ force: true });
Check Button State
const isEnabled = await button.isEnabled();
const isVisible = await button.isVisible();
Complete Example: Video Generation Form
const { chromium } = require('playwright');
const fs = require('fs');
async function submitVideoForm(sessionFile, startImage, endImage, prompt) {
const browser = await chromium.launch({
headless: true,
args: ['--no-sandbox']
});
const context = await browser.newContext();
const page = await context.newPage();
if (fs.existsSync(sessionFile)) {
const session = JSON.parse(fs.readFileSync(sessionFile, 'utf8'));
}
await page.goto('https://example.com/video', {
waitUntil: 'domcontentloaded'
});
await page.waitForTimeout(3000);
const inputs = await page.locator('input[type="file"]').all();
await inputs[].(startImage);
page.();
inputs[].(endImage);
page.();
page.();
page.();
textarea = page.().();
textarea.(prompt, { : });
page.();
page.().({ : });
page.();
page.({ : });
browser.();
}
Scripts
The scripts/ directory contains reusable automation scripts:
webp-compress.sh - Convert images to webp format
form-submit.js - Generic form submission template
Troubleshooting
Button stays gray/disabled
- Wait longer after file upload (3+ seconds)
- Ensure text input triggers events (use pressSequentially)
- Check if images are still uploading
Upload times out
- Compress images to webp format first
- Reduce image dimensions if very large
Form doesn't submit
- Use force: true for click
- Check button selector is correct
- Verify all required fields are filled