microsoft/playwright · error · Error

PDF generation is only supported for Headless Chromium

Error message

PDF generation is only supported for Headless Chromium

What it means

page.pdf() is implemented only by the Chromium browser backend and only in headless mode. The dispatcher checks `this._page.pdf` (a delegate method that is undefined on Firefox/WebKit pages) and throws when it is absent. This is a hard backend-capability limitation, not a configuration toggle.

Source

Thrown at packages/playwright-core/src/server/dispatchers/pageDispatcher.ts:339

  async mouseUp(params: channels.PageMouseUpParams, progress: Progress): Promise<void> {
    await this._page.mouse.apiUp(progress, params);
  }

  async mouseClick(params: channels.PageMouseClickParams, progress: Progress): Promise<void> {
    await this._page.mouse.apiClick(progress, params.x, params.y, params);
  }

  async mouseWheel(params: channels.PageMouseWheelParams, progress: Progress): Promise<void> {
    await this._page.mouse.apiWheel(progress, params.deltaX, params.deltaY);
  }

  async touchscreenTap(params: channels.PageTouchscreenTapParams, progress: Progress): Promise<void> {
    await this._page.touchscreen.apiTap(progress, params.x, params.y);
  }

  async pdf(params: channels.PagePdfParams, progress: Progress): Promise<channels.PagePdfResult> {
    if (!this._page.pdf)
      throw new Error('PDF generation is only supported for Headless Chromium');
    const buffer = await progress.race(this._page.pdf(params));
    return { pdf: buffer };
  }

  async requests(params: channels.PageRequestsParams, progress: Progress): Promise<channels.PageRequestsResult> {
    // Send all future requests to the client, so that it can reliably receive all of them.
    // Otherwise, if subscription is added in a different task from this call (either before or after),
    // there is a chance for a duplicate or a lost request.
    this._subscriptions.add('request');
    return { requests: this._page.networkRequests().map(request => RequestDispatcher.from(this.parentScope(), request)) };
  }

  async bringToFront(params: channels.PageBringToFrontParams, progress: Progress): Promise<void> {
    await this._page.bringToFront(progress);
  }

  async pickLocator(params: channels.PagePickLocatorParams, progress: Progress): Promise<channels.PagePickLocatorResult> {
    const recorder = await progress.race(Recorder.forContext(this._page.browserContext, { omitCallTracking: true, hideToolbar: true }));

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Restrict page.pdf() calls to a chromium-only test project (configure projects in playwright.config to run the pdf spec only under chromium, headless).
  2. Guard the call: `if (browserName === 'chromium') await page.pdf(...)`.
  3. Ensure Chromium is launched headless (headless:true / 'new') — headed Chromium has no pdf backend either.
  4. For Firefox/WebKit, render to an image (page.screenshot fullPage) as an alternative output.

Example fix

// before
test('pdf', async ({ page }) => {
  await page.pdf({ path: 'out.pdf' });
});
// after
test('pdf', async ({ page, browserName }) => {
  test.skip(browserName !== 'chromium', 'PDF is Chromium-only');
  await page.pdf({ path: 'out.pdf' });
});
Defensive patterns

Strategy: validation

Validate before calling

// Guard pdf() by browser type before calling.
if (browserName === 'chromium') {
  await page.pdf({ path: 'out.pdf' });
}

Type guard

// Narrow to a pdf-capable page.
function canPdf(browserName: string): boolean {
  return browserName === 'chromium';
}

Prevention

When it happens

Trigger: Calling page.pdf() inside a test project configured for firefox or webkit; calling page.pdf() on Chromium launched with headless:false; running a shared page-interaction helper across all browser projects that unconditionally calls page.pdf().

Common situations: Cross-browser test suites with a single pdf spec file included in all projects; CI matrix that runs the same spec on chromium+firefox; switching a working Chromium suite to headed mode for debugging and forgetting pdf is called.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/cf6fab2972024cca. Report an issue: GitHub.