microsoft/playwright · error · Error

Playwright Extension not found in

Error message

Playwright Extension not found in "${userDataDir}". Install it from ${playwrightExtensionInstallUrl}, or set the PLAYWRIGHT_MCP_EXECUTABLE_PATH environment variable to use a browser at a custom location.

What it means

Thrown by createExtensionBrowser() when launching in extension mode: no custom executablePath was supplied, a user-data directory was resolved, but findPlaywrightExtensionProfile() could not locate the installed Playwright browser extension in that profile. The error points the user to the extension install URL or to PLAYWRIGHT_MCP_EXECUTABLE_PATH to point at a browser elsewhere. Extension mode requires the extension to be installed so a CDP relay can be established.

Solutions

  1. Install the Playwright browser extension from the URL shown in the error message into the target browser profile, then retry.
  2. Set PLAYWRIGHT_MCP_EXECUTABLE_PATH to a browser binary if you want to bypass extension discovery and point at a specific browser.
  3. Verify the user-data-dir resolution: if you did not pass one, the code uses defaultUserDataDirForChannel(channel) — ensure that profile is the one with the extension.
  4. Confirm the browser channel (chrome/msedge/etc.) matches the profile the extension was installed into.

Example fix

// before
playwright mcp --extension
// after (point at a browser explicitly)
PLAYWRIGHT_MCP_EXECUTABLE_PATH=/usr/bin/google-chrome playwright mcp --extension
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'fs';
async function canUseExtension(channel: string, executablePath?: string, userDataDir?: string) {
  if (executablePath) return true; // bypasses profile discovery
  if (!userDataDir) userDataDir = defaultUserDataDirForChannel(channel);
  const profile = await findPlaywrightExtensionProfile(userDataDir);
  return Boolean(profile);
}

Try / catch

try {
  await createExtensionBrowser(channel, executablePath, userDataDir, clientName);
} catch (e) {
  if (/Playwright Extension not found/.test((e as Error).message)) {
    // guide the user to install the extension or fall back to a direct executable
    throw new Error('Install the Playwright extension or set PLAYWRIGHT_MCP_EXECUTABLE_PATH.');
  }
  throw e;
}

Prevention

When it happens

Trigger: Using --extension (or extension config) for the first time without having installed the Playwright browser extension into the target Chrome/Edge profile; the profile directory was reset or the extension removed; running in an environment (CI/container) where the browser profile has never had the extension added.

Common situations: First-time setup of extension mode; fresh OS/profile; extension auto-removed by the browser; pointing at a profile that belongs to a different channel than the one with the extension installed.

Related errors


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

Appendix: source

Thrown at packages/playwright-core/src/tools/mcp/extensionContextFactory.ts:33

 */

import debug from 'debug';
import { defaultUserDataDirForChannel } from '@utils/chromiumChannels';
import { playwright } from '../../inprocess';
import { findPlaywrightExtensionProfile, playwrightExtensionInstallUrl } from '../utils/extension';
import { CDPRelayServer } from './cdpRelay';

import type * as playwrightTypes from '../../..';

const debugLogger = debug('pw:mcp:relay');

export async function createExtensionBrowser(channel: string, executablePath: string | undefined, customUserDataDir: string | undefined, clientName: string): Promise<playwrightTypes.Browser> {
  customUserDataDir ??= process.env.PWTEST_EXTENSION_USER_DATA_DIR;
  // Custom executablePath may target a browser in a different filesystem (e.g. Windows chrome.exe from WSL2), so the local profile path is not meaningful.
  const userDataDir = customUserDataDir ?? (executablePath ? undefined : defaultUserDataDirForChannel(channel));
  const profileDirectory = userDataDir ? await findPlaywrightExtensionProfile(userDataDir) : undefined;
  if (!executablePath && userDataDir && !profileDirectory)
    throw new Error(`Playwright Extension not found in "${userDataDir}". Install it from ${playwrightExtensionInstallUrl}, or set the PLAYWRIGHT_MCP_EXECUTABLE_PATH environment variable to use a browser at a custom location.`);

  const relay = new CDPRelayServer(channel, executablePath, customUserDataDir, profileDirectory);
  await relay.start();
  debugLogger(`CDP relay server started, extension endpoint: ${relay.extensionEndpoint()}.`);

  try {
    await relay.establishExtensionConnection(clientName);
    const browser = await playwright.chromium.connectOverCDP(relay.cdpEndpoint(), { isLocal: true, timeout: 0, noDefaults: true });
    browser.on('disconnected', () => relay.stop());
    return browser;
  } catch (error) {
    relay.stop();
    throw error;
  }
}

View on GitHub (pinned to c8fc3bf8d3)