Domotion

Troubleshooting

The handful of issues people hit first.

"Cannot find module 'domotion'" or "ERR_MODULE_NOT_FOUND"

Domotion is ESM-only. Make sure your project is set up to load ESM modules:

  • In package.json, set "type": "module".
  • If you can't (e.g. you're inside a CommonJS project), run scripts with tsx: npx tsx your-script.ts.

"browserType.launch: Executable doesn't exist..."

Playwright's Chromium binary isn't installed yet. Run:

npx playwright install chromium

On Linux servers, install the system libraries Chromium needs in addition:

npx playwright install --with-deps chromium

Captured text uses the wrong font / falls back

Two likely causes:

  1. The web font hasn't loaded yet. Add await page.evaluate(() => document.fonts.ready) after your page.setContent or page.goto.
  2. Domotion can't find the font on disk. The bundled mapping table is tuned for macOS system fonts. For other fonts the path renderer falls back to native <text>. Either author your demos in system fonts, or accept the cross-engine font differences. See Fonts & non-Latin scripts.

Captured text drifts left/right across long lines

This usually means the per-character xOffsets array on the text segment is missing — most often because the segment's text was mutated between capture and render. The renderer fell back to summing fontkit advance widths, which accumulates ~0.5px of drift per character against Chromium's sub-pixel positioning.

Fix: avoid mutating el.text after capture. If you need to substitute text, also clear el.textSegments so the renderer re-shapes from scratch with consistent metrics.

Animated SVG flickers between frames

Three possible causes, in order of likelihood:

  1. An overlay is preventing the merge fast path. Even one overlay anywhere in the sequence forces every frame onto the per-frame- atomic path, which can show a one-frame dark flash on transitions. Where you can express the overlaid content as a captured frame instead, it'll both look better and be smaller.
  2. You're using a non-crossfade transition. push-left and scroll use different rendering; they don't flicker but they also can't merge. If you don't need the spatial transition, switching to crossfade usually fixes visual glitches and shrinks the file.
  3. Two frames defined the same SVG ID. Always pass a unique idPrefix per frame to elementTreeToSvg — without it, clip-path / gradient / glyph IDs collide and the wrong shapes get referenced.

Output SVG is huge (> 200 KB)

Three quick wins:

  1. Run optimizeSvg(svg) if you haven't.
  2. Crop to the visible region — capture the smallest viewport that contains the demo content.
  3. Cut frames. Each animation frame is one capture's worth of glyph outlines; aim for 3–5 frames maximum.

See Optimize output size for the full toolkit.

Captured page is missing dynamic content

You captured before the content was rendered. Common pre-capture waits:

// Wait for a known element to appear
await page.waitForSelector(".product-list .item");

// Wait for fonts
await page.evaluate(() => document.fonts.ready);

// Wait for network to settle
await page.goto(url, { waitUntil: "networkidle" });

// Wait for an app-specific signal
await page.waitForFunction(() => window.__appReady === true);

Captured page has running animations frozen at random frames

Pause CSS animations and transitions before capturing so the result is reproducible:

await page.addStyleTag({
  content: `*, *::before, *::after {
    animation-play-state: paused !important;
    transition: none !important;
  }`,
});

Some elements render as solid rectangles

Likely because the element uses a feature Domotion can't reproduce in SVG: backdrop-filter, conic gradient, complex clip-path: path(...). Check the capture warnings:

import { logCaptureWarnings } from "domotion";
logCaptureWarnings();

Each warning identifies the offending selector and feature. See the CSS support overview for the current matrix.

Filing a bug

If you've hit something that isn't on this page or in the FAQ:

  1. Run with capture warnings enabled and include the output.
  2. Include the input HTML and the produced SVG in the report.
  3. Note the Node version, Playwright version, and OS.
  4. If you can, include a Chromium screenshot of the same content (so the expected vs. actual is unambiguous).