Skip to content

[Bug]: connectOverCDP({ noDefaults: true }) still overrides font families (Page.setFontFamilies) on headless browsers #43715

Closed

Description

@rickardof

Version

1.64.1 (reproduced on 1.63.0; the relevant code is unchanged in 1.64.1 and on main)

Steps to reproduce

  1. Start a headless Chrome with a DevTools endpoint. Any headless Chromium build should do, since the code path only depends on the user agent containing Headless:
google-chrome --headless=new --remote-debugging-port=9222 --user-data-dir=/tmp/pw-repro
  1. Save this as repro.js:
const { chromium } = require('playwright');

(async () => {
  const noDefaults = process.env.NO_DEFAULTS !== '0';
  const browser = await chromium.connectOverCDP('http://127.0.0.1:9222', { noDefaults });
  const page = await browser.contexts()[0].newPage();
  await page.goto('about:blank');
  // Leave the attached browser running: exit without browser.close().
  process.exit(0);
})();
  1. Run it with protocol logging and count which default overrides were sent:
DEBUG=pw:protocol node repro.js 2>&1 \
  | grep -oE '"method":"(Page\.setFontFamilies|Emulation\.setFocusEmulationEnabled|Emulation\.setEmulatedMedia)"' \
  | sort | uniq -c

Expected behavior

With noDefaults: true, none of Playwright's default overrides are applied to the existing default context, so the command above prints nothing. From the noDefaults docs: "When true, Playwright will not apply its default overrides to the existing default browser context."

Actual behavior

Focus emulation and media emulation are skipped as documented, but Page.setFontFamilies is still sent to every page of the default context, including tabs that were already open before connecting:

      3 "method":"Page.setFontFamilies"

This is the message that is sent:

{"method":"Page.setFontFamilies","params":{"fontFamilies":{"standard":"Times New Roman","fixed":"Monospace","serif":"Times New Roman","sansSerif":"Arial","cursive":"Comic Sans MS","fantasy":"Impact"}}}

For comparison, NO_DEFAULTS=0 sends all three, as expected.

Additional context

The font defaults are applied in FrameSession._initialize in packages/playwright-core/src/server/chromium/crPage.ts, gated only on headless mode:

if (!browserOptions.headful)
  promises.push(this._setDefaultFontFamilies(this._client));

For connectOverCDP, headful is inferred from the user agent (browser.options.headful = !version.userAgent.includes('Headless') in crBrowser.ts), so this runs for any headless target. The other two defaults next to it are gated on skipDefaultOverrides, which is why only the fonts leak through. The change that added noDefaults (#40185) gated focus and media emulation but left this call as is.

This changes how the user's existing tabs render. In a headless Chrome profile whose fonts are all set to DejaVu Sans Mono, a span of 20 i characters measures 192.7px for every generic family before connecting. Right after connectOverCDP(url, { noDefaults: true }) it measures 88.9px for the default, serif, cursive and fantasy families and 71.1px for sans-serif (numbers from my machine). The override is still in effect in those tabs after Playwright disconnects, until each tab is reloaded. Since Playwright MCP always passes noDefaults for CDP connections (#41676), --cdp-endpoint against a headless Chrome is affected as well.

Proposed fix, gating the call like the other defaults:

if (!browserOptions.headful && !skipDefaultOverrides)
  promises.push(this._setDefaultFontFamilies(this._client));

I tested this change against 1.63.0: with noDefaults: true nothing from the list above is sent and the custom fonts stay at 192.7px; with noDefaults: false the behavior is unchanged. The noDefaults docs could also mention that font families are left alone.

I would like to work on this and can send a PR with the fix and a test in tests/library/chromium/connect-over-cdp.spec.ts.

Environment

System:
  OS: Linux 7.0 Ubuntu 24.04.5 LTS
  CPU: (24) x64 Intel(R) Core(TM) Ultra 9 275HX
  Memory: 62 GB
Binaries:
  Node: 24.21.0
Browsers:
  Google Chrome: 156.0.8078.47 (--headless=new)
npmPackages:
  playwright-core: 1.63.0

Activity

  1. github-actions commented on Oct 29, 2026

    @github-actions
  2. github-actions commented on Oct 29, 2026

    @github-actions
    Contributor

    Hi, I'm the Playwright bot. I reproduced this and prepared a fix.

    Reproduced on Linux with 1.65.0-next (bda54b052be6c5272557f3f1c972ad378bd1dc60), headless Chromium 157.0.8103.15. The font override did not check noDefaults, unlike focus and media emulation. The proposed fix uses the same guard, preserving normal defaults for new contexts.

    Reproduction and checks

    Extended the existing CD-034 should skip default overrides with noDefaults test: set an existing page's standard font to monospace with CDP, measure a span, disconnect, then reconnect with noDefaults: true and compare the width:

    await session.send('Page.setFontFamilies', { fontFamilies: { standard: 'monospace' } });
    await initialPage.setContent('<span>iiiiiiiiiiiiiiiiiiii</span>');
    const width = await initialPage.locator('span').evaluate(span => span.getBoundingClientRect().width);
    await initialBrowser.close();
    const browser = await browserType.connectOverCDP(endpoint, { noDefaults: true });
    const [page] = browser.contexts()[0].pages();
    expect(await page.locator('span').evaluate(span => span.getBoundingClientRect().width)).toBe(width);

    Without the fix, the width changes from 156.546875px to 72.25px. The test failed twice without the fix and passed with it.

    • Chromium headless: full CDP and neighbouring worker connection suites passed under Xvfb (38 passed, 1 existing test marked fixme skipped).
    • Chromium headless and headed: CD-034 and CD-035 passed with the fix (2 tests in each mode).
    • The first full run without Xvfb could not launch an existing headed-only test; rerunning with Xvfb passed.
    • Firefox and WebKit exclude this test file: CDP connections are Chromium-only.
    • npm run build, npm run flint, and git diff --check passed.

    Only the checkout version above was tested, not the reported published versions.

    Draft PR: #43773

    Triaged on Linux by the Playwright bot - agent run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions