Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Yes—browser extensions can run in headless automation, but only with a compatible browser mode and launch configuration. For Playwright, use Chromium with a persistent context and the chromium channel; Chrome for Developers says to use Chrome’s new headless mode rather than old headless. These are documented setup paths, not a guarantee that every extension or CI image will behave identically, so validate the extension workflow in the browser build you actually deploy.
What has to be true for a headless extension test to work?
An extension is not enabled merely because a browser is running without a visible window. The automation framework must launch a browser build and context that support loading extensions, and the launch options must point to the extension files.
- Use an extension-capable Chromium mode. Playwright’s extension instructions use its bundled Chromium with the
chromiumchannel. The Playwright browser documentation distinguishes this browser mode from the default headless shell, which is used when no browser channel is specified. - Use a persistent context in Playwright. Playwright’s Chrome extensions guide says extensions work in Chromium launched with a persistent context.
- Choose new headless mode for Chrome-driven tests. Chrome for Developers’ end-to-end testing guide recommends
--headless=newand says old headless does not support loading extensions. - Check the exact browser and automation versions. The cited documentation describes supported setup approaches, not identical behavior for every extension, browser build, operating system, or CI image.
Playwright recommends its bundled Chromium for the extension setup because Chrome and Edge removed the command-line flags needed to side-load extensions. Do not assume the default headless shell and the chromium channel are interchangeable.
Recommended Free Tools
Run an unpacked extension headlessly with Playwright
The example below uses Node.js, Playwright’s bundled Chromium, a persistent profile directory, and an unpacked extension directory. Replace the two paths with real paths on your machine or CI runner. The extension directory should contain its manifest file, and the persistent profile directory must be writable by the test process.
#1 Best Overall
- Install Playwright and its browser. In a new project, run
npm install playwrightand thennpx playwright install chromium. Use the matching Playwright package and browser installation in CI. - Save the script as
extension-test.cjs. It opens a page in an extension-enabled context and prints the page title. Replace the example destination with a page relevant to your extension’s behavior. - Run it with Node.js. Execute
node extension-test.cjs. The browser is headless; there is no visible window to inspect.
const { chromium } = require('playwright');
const path = require('node:path');
(async () => {
const extensionPath = path.resolve('./my-extension');
const userDataDir = path.resolve('./playwright-profile');
const context = await chromium.launchPersistentContext(userDataDir, {
channel: 'chromium',
headless: true,
args: [
`--disable-extensions-except=${extensionPath}`,
`--load-extension=${extensionPath}`,
],
});
try {
const page = await context.newPage();
await page.goto('https://example.com');
console.log(await page.title());
} finally {
await context.close();
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
The launch configuration is the important part: launchPersistentContext supplies the persistent context, channel: 'chromium' selects the documented extension-capable Playwright browser mode, and the two Chromium arguments load the unpacked extension. The example closes the context in a finally block so the browser does not linger when navigation or assertions fail.
Run headed when visual debugging is more useful
Playwright’s extension guide also identifies headed launch as an option. To see the browser while debugging locally, set headless: false in the same configuration. This changes whether the window is visible; it does not eliminate the need for the persistent context or extension path. A headed run can help diagnose UI interactions, while an unattended CI job generally needs a headless configuration.
Test extension behavior, not just whether the browser opens
A successful launch does not prove that an extension’s content scripts, permissions, popup, or background logic work for your use case. Add assertions for the behavior your users depend on—for example, a page change made by a content script or a result produced after an extension action. Use a page and permissions setup that exercise the relevant path, and run the same test against the browser build and CI image intended for deployment.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Choose the right mode for your automation stack
| Setup | What the documentation establishes | What to validate |
|---|---|---|
| Playwright default headless shell | Playwright uses a separate headless shell when no browser channel is specified. The extension guide’s setup uses a different mode. | Whether the workflow actually needs extension loading, and whether browser-build differences matter to the test. |
Playwright chromium channel with persistent context |
Playwright’s extension guide uses bundled Chromium, a persistent context, and the chromium channel for headless extension testing. |
Extension behavior, profile handling, browser parity needs, and background lifecycle behavior. |
| Chrome new headless mode | Chrome for Developers recommends --headless=new for unattended extension tests and says old headless cannot load extensions. |
Flag compatibility with the Chrome version you install and the browser behavior your test is meant to represent. |
| Headed Playwright | Playwright’s extension guide lists headed operation as an alternative. | Whether local visual debugging is worth requiring a visible browser in that environment. |
These are configuration choices, not a performance ranking: the cited pages do not provide comparative benchmarks. Choose based on extension support, target-browser similarity, debugging needs, and the runtime environment your tests must cover.
Rank #2
Account for Manifest V3 background-worker suspension
Playwright’s extension documentation notes that a Manifest V3 service worker can suspend after 30 seconds of inactivity and then restart. A restart is therefore not automatically evidence that the extension failed to load. Tests should allow for the worker lifecycle and verify the extension’s externally observable behavior rather than assuming a background worker stays resident indefinitely.
The guide also warns that an in-flight evaluate() call can fail if suspension happens at that moment. If a test intermittently fails around background activity, check whether it depends on a long-lived worker or an evaluation that overlaps suspension. Restructure the test around a fresh observable event or result, and rerun it against the exact Playwright and browser versions used in CI.
Chrome guidance outside the Playwright setup
For Chrome-driven extension tests outside the Playwright configuration above, Chrome for Developers’ documented recommendation is new headless mode with --headless=new; the page says old headless does not support loading extensions. Its page also lists Selenium as an extension-testing option, but the cited guidance does not establish a specific Selenium capability configuration. Use the relevant framework’s current documentation rather than copying Playwright’s launch arguments into another framework.
The Chrome page’s search listing is roughly three years old, so check the live guidance and your installed Chrome version before depending on that exact flag. Framework behavior and browser launch options can change; confirm that the selected mode still works in your current test environment.
Rank #3
Troubleshoot common failures
The extension is missing in a Playwright run
- Confirm the test uses
chromium.launchPersistentContext(), not a non-persistent browser context. - Check that
channel: 'chromium'is set for the documented headless extension setup. - Verify that the extension path resolves to the unpacked directory containing its manifest, and that both extension-loading arguments use that exact path.
- Check that the Chromium installation matches the Playwright version used by the project.
The test works headed but not headlessly
Compare the browser mode rather than treating all headless runs as equivalent. Playwright documents a default headless shell and separately demonstrates extension testing with the chromium channel. For Chrome’s own guidance, use new headless rather than old headless. Verify the actual version and flags on the machine where the failure occurs.
The background worker restarts or an evaluation fails
For Manifest V3, a service worker suspension after 30 seconds of inactivity and a subsequent restart are documented lifecycle behavior. Review whether the failing operation relies on the worker remaining active or overlaps suspension; adjust the test to assert behavior after the worker can restart.
It passes locally but fails in CI
Compare the installed Playwright and Chromium versions, extension directory, profile-directory permissions, and launch configuration. A local success does not establish that a different CI image or browser build will behave identically. Reproduce the same extension workflow in the target image before treating the result as a product defect.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
A Selenium recipe is unclear
Do not substitute Playwright-specific arguments or APIs based on assumption. Chrome’s testing guide lists Selenium as an option but does not provide the exact Selenium configuration in the cited guidance. Follow the current Selenium and Chrome documentation for your versions.
Rank #4
Or skip the browser setup
If your goal is a clean screenshot of a page—not to run or validate a browser extension—a screenshot API can avoid maintaining browser launch code. ScreenshotNeo returns a screenshot or PDF from one GET request; it does not run your extension or replace an extension test. Its API removes cookie and consent banners, newsletter popups, and chat widgets before capture, and bot checks, blank pages, and failed loads are not billed. It also provides an MCP server for AI agents to take screenshots.
For a WebP capture, replace the example URL with the page you need. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://example.com
-o shot.webp
ScreenshotNeo’s free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up for free and try ScreenshotNeo.
Performance, reliability, and cost considerations
The sources cited here establish configuration guidance and the Manifest V3 worker lifecycle, not measured speed, reliability rates, or cost comparisons. Plan CI capacity based on your own browser and extension runs; the documented options provide no benchmark from which to predict a runtime advantage. For stable results, pin the project’s browser installation with its Playwright version, keep the extension source and test profile paths explicit, and verify a representative workflow in the deployment image.
Frequently Asked Questions
Does Chrome’s old headless mode load extensions?
Chrome for Developers’ extension testing guide says old headless does not support loading extensions; it recommends new headless mode for unattended extension tests.
Can I use an existing Playwright browser context for an extension?
The Playwright extension guide specifies launching Chromium with a persistent context for extension support.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

