Documentation Index
Fetch the complete documentation index at: https://mintlify.com/microsoft/playwright/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Playwright can capture screenshots and record videos of your tests, providing visual evidence of test execution and helping debug failures.
Screenshots
Full Page Screenshot
Capture a screenshot of the entire page:
import { test, expect } from '@playwright/test';
test('capture full page', async ({ page }) => {
await page.goto('https://example.com');
await page.screenshot({
path: 'screenshot.png',
fullPage: true
});
});
Element Screenshot
Capture a screenshot of a specific element:
test('capture element', async ({ page }) => {
await page.goto('https://example.com');
const element = page.locator('.main-content');
await element.screenshot({ path: 'element.png' });
});
Screenshot Options
await page.screenshot({
path: 'screenshot.png',
fullPage: true,
type: 'png', // 'png' or 'jpeg'
quality: 100, // 0-100 (jpeg only)
});
Visual Regression Testing
Compare Screenshots
Playwright includes built-in visual comparison:
import { test, expect } from '@playwright/test';
test('visual regression', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage.png');
});
Update Baseline Screenshots
When intentional UI changes are made, update baselines:
npx playwright test --update-snapshots
Customize comparison tolerance in playwright.config.ts:
import { defineConfig } from '@playwright/test';
export default defineConfig({
expect: {
toHaveScreenshot: {
maxDiffPixels: 100,
maxDiffPixelRatio: 0.1,
threshold: 0.2,
},
},
});
Video Recording
Enable video recording in your configuration:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
video: 'on', // Record all tests
// video: 'retain-on-failure', // Only failed tests
// video: 'on-first-retry', // Record on retry
videoSize: { width: 1280, height: 720 },
},
});
Video Recording Options
Always record
Records video for all tests. Record failures only
use: {
video: 'retain-on-failure',
}
Only keeps videos of failed tests.Record on retry
use: {
video: 'on-first-retry',
}
Records when tests are retried.Never record
Disables video recording.
Access Video Path
Get the video path programmatically:
import { test } from '@playwright/test';
test('with video', async ({ page }) => {
await page.goto('https://example.com');
// ... test actions ...
});
test.afterEach(async ({ page }, testInfo) => {
if (testInfo.status === 'failed') {
const videoPath = await page.video()?.path();
console.log('Video saved to:', videoPath);
}
});
Screenshot on Failure
Automatic Screenshots
Configure automatic screenshots for failed tests:
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
screenshot: 'only-on-failure',
// screenshot: 'on', // Always capture
// screenshot: 'off', // Never capture
},
});
Custom Failure Handler
Implement custom screenshot logic:
import { test } from '@playwright/test';
test.afterEach(async ({ page }, testInfo) => {
if (testInfo.status !== testInfo.expectedStatus) {
const screenshot = await page.screenshot();
await testInfo.attach('screenshot', {
body: screenshot,
contentType: 'image/png'
});
}
});
test('example test', async ({ page }) => {
await page.goto('https://example.com');
// Test actions...
});
Artifacts Location
Configure where screenshots and videos are saved:
import { defineConfig } from '@playwright/test';
export default defineConfig({
// Output directory for test artifacts
outputDir: 'test-results/',
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
},
});
Practical Examples
Debug Failed Tests
import { test, expect } from '@playwright/test';
test('checkout flow', async ({ page }) => {
await page.goto('https://example.com/shop');
// Take screenshot before critical action
await page.screenshot({ path: 'before-checkout.png' });
await page.click('text=Add to Cart');
await page.click('text=Checkout');
// Take screenshot after critical action
await page.screenshot({ path: 'after-checkout.png' });
await expect(page.locator('.success-message')).toBeVisible();
});
Visual Testing Workflow
import { test, expect } from '@playwright/test';
test.describe('homepage visual tests', () => {
test('desktop view', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage-desktop.png');
});
test('mobile view', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage-mobile.png');
});
test('dark mode', async ({ page }) => {
await page.emulateMedia({ colorScheme: 'dark' });
await page.goto('https://example.com');
await expect(page).toHaveScreenshot('homepage-dark.png');
});
});
Hide Dynamic Content
test('stable screenshot', async ({ page }) => {
await page.goto('https://example.com');
// Hide elements that change frequently
await page.screenshot({
path: 'stable.png',
mask: [
page.locator('.timestamp'),
page.locator('.ad'),
page.locator('.random-content'),
],
});
});
CI/CD Integration
Store artifacts in CI pipelines for easy access:
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 20
- run: npm ci
- run: npm run build
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
Best Practices
Selective Recording: Use retain-on-failure for videos to save disk space while still capturing failures.
- Use visual regression for stable UIs: Only apply visual testing to components with predictable rendering
- Mask dynamic content: Hide timestamps, ads, and random content to reduce false positives
- Set appropriate tolerances: Configure pixel difference thresholds based on your needs
- Store artifacts in CI: Upload screenshots and videos to CI artifacts for easy debugging
- Clean up old artifacts: Implement retention policies to manage disk space
Video recording increases test execution time and storage requirements. Use it judiciously in CI/CD pipelines.
Troubleshooting
Screenshots appear blank
Wait for content to load before capturing:
await page.goto('https://example.com');
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'loaded.png' });
Visual comparison failing unexpectedly
Increase tolerance or update baselines:
await expect(page).toHaveScreenshot('homepage.png', {
maxDiffPixels: 500,
threshold: 0.3,
});
Videos not being saved
Ensure video path is accessible and verify configuration:
test.afterEach(async ({ page }, testInfo) => {
const video = page.video();
if (video) {
const path = await video.path();
console.log('Video path:', path);
}
});