Browser automation tools are convenient until each project quietly downloads another browser. On macOS, Puppeteer and Playwright can each keep several gigabytes of Chromium builds in their caches, even when Google Chrome is already installed and up to date.

For local automation that only needs Chrome, I use the system browser instead. That reclaimed more than 4 GB on my machine and still lets Puppeteer, Playwright Test, Playwright CLI, and Playwright MCP do their jobs.

This is a local-development optimization, not a replacement for Playwright's pinned browsers. Keep reading for the trade-offs.

Check what is using the space

Puppeteer and Playwright keep their downloaded browsers in separate macOS caches. Check their sizes before deleting anything:

du -sh ~/.cache/puppeteer 2>/dev/null
du -sh ~/Library/Caches/ms-playwright 2>/dev/null

Enter fullscreen mode Exit fullscreen mode

~/.cache/puppeteer contains Puppeteer's downloaded Chrome or Chrome for Testing builds. ~/Library/Caches/ms-playwright contains the browsers installed for Playwright.

First make sure that regular Google Chrome is installed at the standard macOS location:

test -x "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  && echo "Google Chrome is available"

Enter fullscreen mode Exit fullscreen mode

Point Puppeteer at system Chrome

Set PUPPETEER_EXECUTABLE_PATH to make Puppeteer use the already-installed Google Chrome executable:

export PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

Enter fullscreen mode Exit fullscreen mode

Add that export to the shell profile you use for local automation, such as ~/.zshrc, if it should persist between terminals.

Puppeteer can also be configured explicitly in code. This is useful when a project should be self-contained instead of relying on its caller's environment:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
  headless: true,
});

const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.pdf({ path: 'example.pdf', format: 'A4' });
await browser.close();

Enter fullscreen mode Exit fullscreen mode

Run a real workflow, such as PDF generation, before removing the cache. It confirms that permissions, launch arguments, and any fonts used by your automation work with system Chrome.

Configure Playwright to use Chrome

Playwright treats installed, branded browsers as channels. Choosing the chrome channel selects the regular Google Chrome installation rather than Playwright's bundled Chromium.

For Playwright Test, configure the project with channel: 'chrome':

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    {
      name: 'Google Chrome',
      use: { ...devices['Desktop Chrome'], channel: 'chrome' },
    },
  ],
});

Enter fullscreen mode Exit fullscreen mode

For one-off browsing with Playwright CLI, select the same channel:

playwright-cli open https://example.com --browser=chrome

Enter fullscreen mode Exit fullscreen mode

Playwright MCP accepts the browser either as an argument or an environment variable:

npx @playwright/mcp@latest --browser chrome

export PLAYWRIGHT_MCP_BROWSER=chrome

Enter fullscreen mode Exit fullscreen mode

If Chrome is installed somewhere nonstandard, Playwright MCP also provides --executable-path for an explicit executable location.

Optionally default Playwright CLI to Chrome

Passing --browser=chrome is explicit and works well for one-off commands. If every local playwright-cli session should use regular Chrome, use the CLI's global configuration instead of a shell function. Create ~/.playwright/cli.config.json:

mkdir -p ~/.playwright

Enter fullscreen mode Exit fullscreen mode

{
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "channel": "chrome"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

The global config applies to every playwright-cli command, including open, without modifying ~/.zshrc. A project-level .playwright/cli.config.json or an explicit option still overrides it when a workflow needs a different browser:

playwright-cli open https://example.com
playwright-cli open https://example.com --browser=firefox

Enter fullscreen mode Exit fullscreen mode

Skipping downloads is not browser selection

This environment variable prevents Playwright from downloading browser binaries:

export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1

Enter fullscreen mode Exit fullscreen mode

It does not tell Playwright which browser to launch. Without channel: 'chrome', --browser=chrome, a Playwright CLI global or project config, PLAYWRIGHT_MCP_BROWSER=chrome, or another explicit configuration, a workflow may still expect Playwright's bundled Chromium.

Likewise, PUPPETEER_EXECUTABLE_PATH selects an executable for Puppeteer; it does not remove browser files which have already been downloaded.

Clean caches after verification

Once the Puppeteer script and relevant Playwright workflows succeed with Chrome, remove the downloaded browser caches:

rm -rf ~/.cache/puppeteer
rm -rf ~/Library/Caches/ms-playwright

Enter fullscreen mode Exit fullscreen mode

Run the size check again to confirm the disk space has been recovered:

du -sh ~/.cache/puppeteer ~/Library/Caches/ms-playwright 2>/dev/null

Enter fullscreen mode Exit fullscreen mode

The next project that needs a managed browser can download it again. If cache location is the concern rather than cache size, Puppeteer supports PUPPETEER_CACHE_DIR and Playwright supports PLAYWRIGHT_BROWSERS_PATH to store downloads elsewhere.

Keep managed browsers where they matter

System Chrome is a good choice for local Chrome-only automation. It is not a substitute for the browser binaries pinned by Playwright:

  • Use Playwright-managed browsers when testing Chromium, Firefox, or WebKit.
  • Use them in CI when reproducibility matters more than saving local disk space.
  • Keep the official Playwright Docker or DevContainer image for containerized tests. Its matching browser binaries live inside the container image, so deleting host caches does not affect those runs.

The practical split is simple: use system Chrome for local automation that targets Chrome, and keep Playwright's managed browsers where cross-browser coverage and repeatability are part of the requirement.


Keep automating. 🫡