
Playwright Recording
Capture deterministic browser recordings with Playwright context video options for demos, QA evidence, and launch assets.
Overview
Playwright Recording is an agent skill most often used in Ship (also Build frontend, Launch distribution) that documents Playwright APIs for context-level video capture of browser sessions.
Install
npx skills add https://github.com/digitalsamba/claude-code-video-toolkit --skill playwright-recordingWhat is this skill?
- RecordVideoOptions reference with required dir and optional size for context-level capture
- chromium.launch knobs: slowMo, headless, devtools, and common recording-friendly args
- Page navigation, waitUntil modes, networkidle waits, and interaction helpers for scripted demos
- Viewport, locale, timezone, geolocation, and userAgent context flags for realistic recordings
- Three waitUntil navigation modes documented: load, domcontentloaded, networkidle
Adoption & trust: 590 installs on skills.sh; 1.4k GitHub stars; 1/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need a repeatable way to record your app in the browser but keep forgetting Playwright video options and wait semantics.
Who is it for?
Indie devs shipping web UIs who want code-first demo and test recordings inside their agent workflow.
Skip if: Native mobile capture, desktop apps outside Chromium, or teams that only need static screenshots.
When should I use this skill?
You are implementing or debugging Playwright-based browser video capture for demos, tests, or marketing clips.
What do I get? / Deliverables
You get agent-generated Playwright scripts with correct recordVideo setup, launch args, and stable navigation or interaction sequences for exported video files.
- Playwright script with recordVideo configuration
- Video files written to the chosen output directory
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
Primary shelf is Ship/testing because Playwright recording is the standard path for reproducible browser sessions and visual proof. Testing subphase covers E2E capture, wait strategies, and interaction APIs used while validating UI flows on video.
Where it fits
Record a checkout flow with networkidle waits to attach visual proof to a release checklist.
Script a dark-mode dashboard tour with fixed viewport dimensions for design review.
Export a hero demo mp4 for a Product Hunt post using slowed interactions.
Capture pre-release smoke paths as video artifacts alongside manual launch QA.
How it compares
Use this reference skill for Playwright-encoded capture—not ad hoc OS screen recorders that break on CI headless runs.
Common Questions / FAQ
Who is playwright-recording for?
Solo web builders using Claude Code or similar agents to script Playwright sessions that output video from real browser automation.
When should I use playwright-recording?
In Ship/testing while documenting E2E flows; in Build/frontend when prototyping motion-sensitive UI tours; in Launch/distribution when producing product demo clips for landing pages or social.
Is playwright-recording safe to install?
It guides local browser automation that can hit your dev servers—review the Security Audits panel on this Prism page and scope network targets deliberately.
SKILL.md
READMESKILL.md - Playwright Recording
# Playwright Recording Reference ## API Reference ### Browser Context Video Options ```typescript interface RecordVideoOptions { dir: string; // Output directory (required) size?: { width: number; height: number }; // Video dimensions } const context = await browser.newContext({ viewport: { width: number; height: number }; recordVideo: RecordVideoOptions; // Other useful options: colorScheme?: 'light' | 'dark' | 'no-preference'; locale?: string; // e.g., 'en-US' timezoneId?: string; // e.g., 'America/New_York' geolocation?: { latitude: number; longitude: number }; permissions?: string[]; // e.g., ['geolocation'] userAgent?: string; }); ``` ### Browser Launch Options ```typescript const browser = await chromium.launch({ slowMo?: number; // Slow down actions by ms headless?: boolean; // Default true, set false to see browser devtools?: boolean; // Open devtools args?: string[]; // Chromium flags }); // Useful args: args: [ '--start-maximized', '--disable-infobars', '--hide-scrollbars', ] ``` ### Page Methods for Recording ```typescript // Navigation await page.goto(url, { waitUntil?: 'load' | 'domcontentloaded' | 'networkidle' }); await page.goBack(); await page.goForward(); await page.reload(); // Waiting await page.waitForTimeout(ms); await page.waitForLoadState('networkidle'); await page.waitForSelector(selector); await page.waitForURL(urlPattern); // Interactions await page.click(selector); await page.dblclick(selector); await page.fill(selector, value); await page.type(selector, text); // Types character by character await page.press(selector, key); // e.g., 'Enter', 'Tab' await page.hover(selector); await page.selectOption(selector, value); await page.check(selector); // Checkbox await page.uncheck(selector); // Scrolling await page.evaluate(() => window.scrollTo(0, 500)); await page.evaluate(() => window.scrollBy(0, 200)); await page.locator(selector).scrollIntoViewIfNeeded(); // Screenshots (for thumbnails) await page.screenshot({ path: 'screenshot.png' }); await page.screenshot({ path: 'full.png', fullPage: true }); ``` ### Getting Video After Recording ```typescript const page = await context.newPage(); // ... do stuff ... await context.close(); // Get video path const video = page.video(); const path = await video?.path(); // Or save to specific location await video?.saveAs('output.webm'); // Delete video await video?.delete(); ``` ## Common Selectors ```typescript // CSS Selectors await page.click('button'); await page.click('#submit-btn'); await page.click('.primary-button'); await page.click('[data-testid="login"]'); await page.click('button:has-text("Submit")'); // Text selectors await page.click('text=Click me'); await page.click('text="Exact match"'); // XPath await page.click('xpath=//button[@type="submit"]'); // Combining await page.click('form >> button.submit'); await page.click('div.modal >> text=Confirm'); ``` ## Timing Utilities ```typescript // Reusable delay function const delay = (ms: number) => new Promise(r => setTimeout(r, ms)); // Smooth typing with delays async function typeSlowly(page, selector, text, delayMs = 100) { await page.click(selector); for (const char of text) { await page.keyboard.type(char); await delay(delayMs); } } // Wait for animation to complete async function waitForAnimation(page, selector) { await page.waitForFunction( (sel) => { const el = document.querySelector(sel); if (!el) return false; const style = getComputedStyle(el); return style.animationName === 'none' || style.animationPlayState === 'paused'; }, selector ); } ``` ## Device Emulation ```typescript import { devices } from 'playwright'; // iPhone const context = await browser.newContext({ ...devices['iPhone 14'], recordVideo: { dir: './recordings' } }); // iPad const context = await browser.newContext({ ...devices['iPad Pro 11'],