npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

playwright-trace-player

v1.0.2

Published

Replay Playwright trace screenshots in any browser, with a small React player included.

Readme

Playwright Trace Player

Replay any Playwright trace as a video-like view in the browser. Pass a trace URL to the React component to review or share any run.

The package reads the screencast frames that Playwright already stores in trace.zip. It needs no server process, ffmpeg, video export, or Playwright runtime. It keeps screenshots compressed until playback reaches them and holds only a small set of image URLs, so large traces do not expand all at once.

In browsers, trace download, ZIP parsing, and screenshot inflation run in a module Worker automatically. React users do not need to create or manage it. Apps with a strict Content Security Policy must allow workers from the app origin with worker-src 'self'.

Install

npm install playwright-trace-player

React

import { PlaywrightTracePlayer } from 'playwright-trace-player/react'
import 'playwright-trace-player/styles.css'

export function TraceReplay({ traceUrl }: { traceUrl: string }) {
  return (
    <PlaywrightTracePlayer
      traceUrl={traceUrl}
      className="w-80"
    />
  )
}

The player has play, pause, seek, speed, keyboard, and full-screen controls. Its display settings can show Playwright commands, recorded cursor movement, click markers, keyboard input, browser details, and the trace result.

Props

| Prop | Type | Default | Use | | --- | --- | --- | --- | | traceUrl | string | — | URL of a Playwright trace.zip | | trace | URL \| File \| Blob \| ArrayBuffer \| Uint8Array | — | Direct trace source; takes priority over traceUrl | | pageId | string | page with most frames | Select a page when a trace has popups | | autoPlay | boolean | false | Start after the trace loads | | loop | boolean | false | Start again at the end | | playbackRate | number | 1 | Initial speed | | showControls | boolean | true | Show the control bar | | defaultSettings | Partial<PlaywrightTracePlayerSettings> | all visible | Set the initial choices in the display-settings popover | | className | string | — | Apply CSS, Tailwind utilities, or design-system classes | | style | PlaywrightTracePlayerStyle | — | Apply inline CSS and typed player theme tokens | | requestInit | RequestInit | — | Send headers or credentials with the trace request | | onLoad | (trace) => void | — | Read parsed trace data | | onError | (error) => void | — | Handle a load or parse error | | onTimeUpdate | (seconds) => void | — | Follow playback time |

Styling

The player exposes four main CSS tokens. Map them to your app's design tokens once; every player will follow the active theme:

[data-playwright-trace-player] {
  --ptp-background: var(--app-background);
  --ptp-accent: var(--app-accent);
  --ptp-radius: var(--app-radius);
  --ptp-font-family: var(--app-font);
}

For a Tailwind v4 theme with semantic colors, put the mapping in your global CSS:

@layer components {
  [data-playwright-trace-player] {
    --ptp-background: var(--color-background);
    --ptp-foreground: var(--color-foreground);
    --ptp-accent: var(--color-primary);
    --ptp-accent-foreground: var(--color-primary-foreground);
    --ptp-radius: var(--radius-lg);
    --ptp-font-family: var(--font-sans);
  }
}

Then use normal Tailwind utilities for size and layout:

<PlaywrightTracePlayer
  traceUrl={traceUrl}
  className="w-80 max-w-full"
/>

Current shadcn themes can map their base tokens directly:

@layer components {
  [data-playwright-trace-player] {
    --ptp-background: var(--background);
    --ptp-foreground: var(--foreground);
    --ptp-accent: var(--primary);
    --ptp-accent-foreground: var(--primary-foreground);
    --ptp-radius: var(--radius);
    --ptp-font-family: inherit;
  }
}

Player tokens inherit, so you can also set them on a theme wrapper. Dark-mode and tenant themes then work without changing the player. If your system uses different token names, change only the mapping.

For more control, set --ptp-muted, --ptp-danger, --ptp-border-color, --ptp-viewport-background, or --ptp-max-viewport-height. The typed style prop remains available for one-off values, while className accepts normal CSS and layout utilities.

The ref exposes play(), pause(), and seek(seconds).

The keyboard and pointer settings use three display levels:

<PlaywrightTracePlayer
  traceUrl={traceUrl}
  defaultSettings={{
    keyboardInput: 'markers-only',
    pointer: 'full',
    showPlaywrightCommands: false,
  }}
/>
  • keyboardInput: 'full' shows keys such as Tab, Enter, and the arrow keys, plus typed values when the trace contains them. Use 'markers-only' to show that keyboard input happened while redacting its value from both the key overlay and command caption, or 'hidden' to remove it.
  • pointer: 'full' shows recorded movement and click feedback. Use 'markers-only' for click feedback alone, or 'hidden' to remove both.

The other settings are showTraceResult, showBrowserName, and showPlaywrightCommands. Each is a boolean. The trace result is hidden by default; when shown, it reports whether the selected page timeline contains recorded action errors. Cursor movement is only as detailed as the trace: explicit mouse moves provide a path, while many locator actions provide only a click point.

Framework-free core

Use the parser without React and bring your own view:

import { loadTrace, selectTraceTimeline } from 'playwright-trace-player'

const trace = await loadTrace('https://example.com/trace.zip')
const timeline = selectTraceTimeline(trace)

console.log(timeline.frames, timeline.actions, timeline.duration)
const firstScreenshot = await trace.readFrame(timeline.frames[0])
trace.dispose()

loadTrace accepts the same URL, file, blob, and byte sources as the React component. In browsers it uses the same automatic Worker. It can report download progress and accepts an abort signal. Frame data loads on demand. Call dispose() when a framework-free player no longer needs the trace. The React component does this for you.

const trace = await loadTrace(traceUrl, {
  signal: controller.signal,
  requestInit: { credentials: 'include' },
  onProgress: ({ phase, loadedBytes, totalBytes }) => {
    console.log(phase, loadedBytes, totalBytes)
  },
})

Record usable traces

Playwright must save screenshots in the trace. The test runner does this for its normal trace modes. Use on to record every run, or choose another mode that fits your retention policy:

// playwright.config.ts
export default defineConfig({
  use: {
    trace: 'on',
  },
})

If you use the tracing API yourself, turn screenshots on:

await context.tracing.start({ screenshots: true, snapshots: true })
// ...run the automation...
await context.tracing.stop({ path: 'trace.zip' })

Serving traces

The browser must be able to fetch the full ZIP. If the trace sits on another host, that host must allow your app origin with CORS. Signed object-store URLs work well.

Access-Control-Allow-Origin: https://your-app.example
Content-Type: application/zip

Large traces use more browser memory because the player unzips their screencast images locally. Keep trace retention and size limits in mind.

What this is not

This package replays screenshots. It does not render an MP4, rebuild an interactive DOM, or show the full network and source panels from Playwright Trace Viewer. It aims to answer one quick question: “What happened during this run?”

Credit

This project takes inspiration from playwright-recast, an MIT-licensed tool for turning Playwright traces into videos.

License

MIT