Skip to main content
/tayyab/portfolio — zsh
tayyab
TA
// dispatch.read --classified=false --access-level: public

Playwright Screencast API: Generate Stakeholder-Ready Test Videos (1.59 Feature Walkthrough)

April 27, 2026 EST. READ: 11 MIN #Quality Assurance

If you've ever sent a stakeholder a 12-minute test run video with no narration, no labels, and no idea where the important moment is, you know why the new Screencast API in Playwright 1.59 matters. The old video option records the browser. The Screencast API records the browser and annotates what happened, with chapter titles, action markers, and visual overlays you control from the test code.

I've been using it on a fintech client where every release cycle includes a video demo for the compliance team. The old workflow was: run the test, screen-record the trace viewer, edit it in CapCut, hope the timestamps line up. The new workflow is: run the test, get an annotated MP4, attach it to the PR. Saves about 90 minutes per release.

This article is the practical guide: how to enable it, the five capabilities it gives you, what's actually useful, and what I'd skip.

Table of Contents

What the Screencast API Actually Is

Don't confuse it with the existing use: { video: 'on' } option — that still exists and still records raw video. Screencast is additive: it gives you imperative control over what gets captured and adds an annotation layer on top of the video.

The official release notes call out five capabilities:

  1. Programmatic start/stop control
  2. Action annotations that highlight elements being interacted with
  3. Visual overlays for chapter titles and custom HTML
  4. Real-time frame capture for streaming JPEG frames to external tools
  5. "Agentic video receipts" for visual proof of automated work

I'll walk through each. Some of them are more useful than the marketing suggests, some less.

Enabling It in Your Config

// playwright.config.ts (1.59+)
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    screencast: {
      mode: 'on',                  // 'on' | 'on-first-retry' | 'retain-on-failure' | 'off'
      dir: './test-results/videos',
      width: 1280,
      height: 720,
      // Annotation defaults:
      annotateActions: true,
      annotateAssertions: false,
    },
  },
});

One subtle thing: mode: 'on' records every test. retain-on-failure only keeps videos for failing tests, which is what I run in CI. The annotateActions: true draws the bounding box overlay; turn it off if you want clean video.

The output is a regular MP4 you can attach to PRs, embed in Confluence, send to clients. It's not a special format requiring the trace viewer.

Capability 1: Programmatic Recording Control

You can start, pause, and stop recording mid-test:

test('checkout flow with selective recording', async ({ page, context }) => {
  await page.goto('/cart');

  // Boring setup - skip recording
  await page.getByRole('button', { name: 'Apply coupon' }).click();
  await page.waitForResponse('**/api/coupons/**');

  // Start recording the interesting part
  const screencast = await context.screencast.start({
    name: 'checkout-payment',
  });

  // ... payment flow ...
  await page.getByRole('button', { name: 'Pay $49.99' }).click();
  await expect(page).toHaveURL(/\/thank-you/);

  await screencast.stop();
});

This is genuinely useful when your test has 60 seconds of setup and 10 seconds of "the actual thing." Stakeholders only want to see the actual thing.

Capability 2: Action Annotations

By default, every Playwright action (click, fill, etc.) draws a brief highlighted box on the recorded video. The box shows what was interacted with. For someone who didn't write the test, this is the difference between "a button got clicked somewhere" and "the user clicked the Pay button at 0:14."

If you want more context, annotate manually:

await page.screencast.annotate({
  text: 'Verifying tax calculation',
  position: 'top-right',
  duration: 2000, // ms
});
await expect(page.getByTestId('tax-amount')).toHaveText('$3.75');

Use sparingly. The auto-annotations are usually enough; manual ones add noise if you sprinkle them everywhere.

Capability 3: Chapter Markers and Titles

This is the one I use most. A chapter is a labeled section of the video — like a YouTube chapter. Stakeholders can jump to "Login," "Add to Cart," "Payment" without scrubbing.

test('full checkout - annotated for stakeholders', async ({ page }) => {
  await page.screencast.chapter('Login');
  await page.goto('/login');
  // ... login ...

  await page.screencast.chapter('Browse products');
  await page.goto('/products');
  // ... browsing ...

  await page.screencast.chapter('Checkout');
  await page.getByRole('button', { name: 'Checkout' }).click();
  // ... checkout ...

  await page.screencast.chapter('Payment confirmation');
  await expect(page).toHaveURL(/\/thank-you/);
});

The video that comes out has a sidebar with clickable chapters. The compliance team on the fintech project loves this because they can verify "yes, the OFAC screening step happened" without watching the whole 4-minute test.

Capability 4: Custom HTML Overlays

Inject arbitrary HTML over the recorded video. This is overkill for most teams, but useful when you want to show, say, the API response that just came back inline:

const response = await page.waitForResponse('**/api/orders');
const body = await response.json();

await page.screencast.overlay({
  html: `<div style="background: rgba(0,0,0,0.8); color: lime; padding: 12px; font-family: monospace;">
    Order created: ${body.id}<br>Status: ${body.status}
  </div>`,
  position: { top: 20, right: 20 },
  duration: 3000,
});

I'd skip this for normal test runs — too much code in a test file. But for a one-off demo recording, it's nice.

Capability 5: Real-Time Frame Streaming

This is the agentic-workflow capability — pipe JPEG frames to a service that does something with them in real time. The use case is: an LLM agent watching the test execute and adapting its plan based on what it sees.

const stream = await page.screencast.streamFrames({
  format: 'jpeg',
  quality: 70,
  fps: 10,
});

stream.on('frame', async (frame) => {
  // Send to your agent's vision API:
  await fetch('http://localhost:3001/agent/observe', {
    method: 'POST',
    body: frame.data,
  });
});

Honest take: I have not used this in production. The latency of streaming frames over HTTP to an LLM is high enough that the agent can't react in real time anyway. It's interesting for research; for shipping client work, irrelevant. Skip.

My Current Workflow

For each release on the fintech client:

  1. Tag a critical-path test with @stakeholder-demo
  2. Add chapter markers at the major flow steps (login, search, transact, confirm)
  3. CI runs the test with screencast.mode: 'on' and uploads the MP4 as a build artifact
  4. Release notes link to the artifact: "see test run video"
  5. Compliance team watches it once, signs off, moves on

Total work to set up was about 90 minutes. Time saved per release: ~90 minutes. I broke even on the first release and it's been pure savings since.

What I'd Skip

  • Recording every test in CI. Storage adds up, almost nobody watches the videos. Use retain-on-failure.
  • Manual annotations on every action. The auto-annotations are sufficient. Manual annotations are for the 5–10 "this is the moment" callouts.
  • HTML overlays in production tests. Looks impressive, becomes maintenance overhead. Reserve for demo-specific recordings.
  • Real-time frame streaming. Cool capability, no real-world value yet for typical test workflows.
  • Recording at 1080p or higher. File sizes balloon and stakeholders can't tell the difference. 1280×720 is plenty.

FAQs

Does this replace the old video option?

No. video: 'on' still records raw browser footage. Screencast adds annotation, chapter, overlay capabilities on top. They can coexist.

What's the file size impact?

Roughly 8–15MB per minute at 1280×720. A typical 90-second checkout flow is ~15MB. Storage on GitHub Actions artifacts is generous; on cheaper CI providers, watch your retention.

Can I add audio narration?

Not natively. You'd need to post-process the MP4 with FFmpeg. For most stakeholder use cases, chapter markers + auto-annotations replace the need for narration.

Does it work with Playwright Component Testing?

Yes, but the recordings are usually less interesting (you're recording an isolated component, not a full flow). I rarely enable it for component tests.

Will it slow down my tests?

Negligibly. Maybe 5–10% slower for tests that are heavy on DOM mutation. For most test suites, you won't notice.

Can I use this with headless mode?

Yes — that's the default. You don't need a visible browser to record.

What about Safari/WebKit and Firefox?

Screencast works on all three engines. Annotation styling may render slightly differently across engines, but the core functionality is consistent.

How do I attach the video to a Slack thread automatically?

In CI, after the test run, upload the MP4 to S3 (or wherever) and post a message via the Slack API with the URL. Most teams already have a similar pattern for test reports.

Is the video format MP4 or WebM?

MP4 by default in 1.59. You can configure WebM via screencast: { format: 'webm' } if you need broader compatibility.

Does the agentic-workflow streaming have a stable API?

Marked experimental in 1.59. Expect breaking changes in 1.60+. Don't build production tooling on it yet.

Wrap-Up

Screencast is the most practical addition in 1.59 for non-AI use cases. Chapter markers alone are worth the upgrade if you regularly demo your tests to non-technical stakeholders. Skip the more exotic capabilities until you have a specific use case for them.

If your team has stakeholder demo overhead and you want help wiring this into your CI workflow, that's part of what I do in framework engagements. Or book a free call.

Related reading:

Tayyab Akmal
// author

Tayyab Akmal

AI & QA Automation Engineer

6 years of catching critical bugs in fintech, e-commerce, and SaaS — then building the Playwright and Selenium automation that prevents them from shipping again.

// feedback_channel

FOUND THIS USEFUL?

Share your thoughts or let's discuss automation testing strategies.

→ Start Conversation
Available for hire