Skip to content

Feature Request: Built-in session video recording via Page.startScreencast #19

@crayment

Description

@crayment

Feature Request: Built-in session video recording via Page.startScreencast

Summary

Add a high-level recording abstraction to cdp_use that uses the CDP Page.startScreencast / Page.screencastFrame / Page.stopScreencast protocol to capture a browser session as a video file.

Motivation

CDP has native support for streaming browser frames via Page.startScreencast. This makes it possible to record headless browser sessions without needing external tools like ffmpeg screen capture (which doesn't work in headless mode) or Playwright's recording feature (which is not available in cdp_use).

Use cases:

  • Debugging automated browser sessions after the fact
  • Generating video artifacts from CI/test runs
  • Recording user flow walk-throughs driven by agents (e.g. first-time UX testing)

What CDP supports today

The protocol already has everything needed:

# Start streaming frames
await cdp.send("Page.startScreencast", {
    "format": "jpeg",
    "quality": 80,
    "maxWidth": 1280,
    "maxHeight": 800,
    "everyNthFrame": 1
})

# Each frame arrives as an event
@cdp.on("Page.screencastFrame")
async def on_frame(event):
    frame_data = event["data"]  # base64-encoded JPEG
    session_id = event["sessionId"]
    # acknowledge receipt
    await cdp.send("Page.screencastFrameAck", {"sessionId": session_id})

# Stop when done
await cdp.send("Page.stopScreencast")

Frames can then be encoded to .webm or .mp4 using ffmpeg or a pure-Python encoder like imageio.

Proposed API

A simple, ergonomic recording context manager on the CDP client or page:

async with cdp.record_video("/tmp/session.webm", fps=10, width=1280, height=800):
    await cdp.send("Page.navigate", {"url": "https://example.com"})
    # ... do stuff
# video saved to /tmp/session.webm when context exits

Or a lower-level start/stop pair:

recorder = await cdp.start_recording("/tmp/session.webm")
# ... do stuff
await recorder.stop()  # saves the file

Alternatives considered

  • ffmpeg screen capture: doesn't work in headless mode
  • Playwright record_video_dir: requires Playwright, not available in cdp_use
  • Screenshot stitching: produces a slideshow, not a real recording; frame timing is lost
  • Laminar / external observability platforms: too heavyweight for simple local use

Notes

  • Page.startScreencast works in headless Chromium — this is how Cypress and other tools implement their video recording
  • Frame encoding to video could be an optional dependency (e.g. pip install cdp-use[video]) to keep the base install lightweight
  • Quality and frame rate should be configurable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions