Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsUse Playwright or Puppeteer to control a real browser without opening a window. Install the package and a compatible browser, launch it in headless mode, create a page, navigate or interact, collect text or a screenshot, and close the browser in a finally block. Playwright is the better default when you need Chromium, Firefox and WebKit; Puppeteer is a straightforward Chrome-focused choice with a managed Chrome download.
What “headless browser” means
A headless browser runs the same page-loading and JavaScript-rendering engine as a normal browser, but without a visible window. Your script can open pages, fill forms, click controls, wait for dynamic content, read the DOM, generate PDFs and save screenshots. It is useful for testing, scraping pages you are allowed to access, rendering reports and automating repetitive browser work.
Headless does not mean “HTTP client only.” The browser still downloads resources, executes JavaScript and may encounter consent banners, bot checks, authentication and timing issues. Treat it as a real browser running under program control.
Choose Playwright or Puppeteer
| Decision | Playwright | Puppeteer |
|---|---|---|
| Browser coverage | Chromium, Firefox and WebKit are documented targets. | High-level automation for Chrome or Firefox; its ecosystem is especially Chrome-centered. |
| Browser provisioning | Install matching browser builds with the Playwright CLI. | puppeteer normally downloads a compatible Chrome; puppeteer-core expects you to provide a browser. |
| Best fit | Cross-engine testing or explicit control of browser binaries. | A compact Chrome-oriented script or an existing managed browser. |
| Headless choices | Regular Chromium headless uses a separate shell; a Chromium channel can select newer headless behavior. | Default headless mode, plus headless: 'shell' for Chrome Headless Shell. |
There is no controlled benchmark here that proves one library is universally faster or more reliable. Test the exact browser, mode and workload you will deploy. Check the current Playwright installation documentation for release-specific Node.js and operating-system requirements.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRun a browser with Playwright
Install a new project
- Install a current Node.js release supported by your chosen Playwright version.
- For the official starter project, run
npm init playwright@latestand choose JavaScript when prompted. - For a library-only script, install the package with
npm install playwright. - Download browser binaries with
npx playwright install. To install only WebKit, usenpx playwright install webkit.
Playwright browser builds are coupled to Playwright releases. After upgrading the package, rerun the installer if the required executable is missing. On Linux CI, npx playwright install --with-deps chromium installs Chromium and documented operating-system dependencies. If you only need the headless shell, Playwright also documents --only-shell.
#1 Best Overall
Minimal JavaScript screenshot
const { webkit } = require('playwright');
(async () => {
const browser = await webkit.launch();
try {
const page = await browser.newPage();
await page.goto('https://playwright.dev/', { waitUntil: 'load' });
await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
await browser.close();
}
})();
Browsers launch headlessly by default in the documented library flow. The try/finally ensures that a timeout or extraction error does not leave a browser process running.
Read page text and wait for application content
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded', timeout: 30_000 });
await page.waitForSelector('h1', { state: 'visible', timeout: 10_000 });
const title = await page.title();
const heading = await page.locator('h1').innerText();
console.log({ title, heading });
} finally {
await browser.close();
}
})();
Use domcontentloaded when you need the initial document quickly, load when page resources must finish, or an explicit selector when a single application element proves that rendering is ready. Network-idle waits can be useful for apps that load data after navigation, but never assume that a permanently open analytics or websocket connection will become idle.
Choose a different headless Chromium mode
Playwright documents regular headless Chromium with a separate headless shell and a newer mode selected through the chromium channel. If you need only the newer mode, npx playwright install --no-shell avoids downloading the separate shell. Mode differences can affect rendering and automation behavior, so pin and test the mode used in development and CI.
Run a browser with Puppeteer
Install the managed-Chrome package
- Run
npm install puppeteer. The package normally downloads a compatible Chrome during installation. - If your package manager blocks install scripts, run
npx puppeteer browsers installor allow the Puppeteer install script. - Use
puppeteer-coreonly when you manage the browser yourself or connect to a remote browser; it does not download Chrome.
The package and installation details are covered in the Puppeteer documentation index and installation guide.
Rank #2
Minimal Puppeteer script
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'example.png', fullPage: true });
} finally {
await browser.close();
}
With CommonJS, use const puppeteer = require('puppeteer') and place the same lifecycle in an async function. The getting-started flow is launch, create a page, navigate, manipulate or extract, then close; Puppeteer is headless by default.
Use Chrome Headless Shell deliberately
const browser = await puppeteer.launch({ headless: 'shell' });
Puppeteer documents shell mode as potentially more performant when the full feature set is unnecessary, but it does not completely match regular Chrome. Choose it only after checking that your page and automation do not depend on the missing behavior. Use the default headless mode when fidelity to normal Chrome matters more.
Make scripts dependable
Set explicit timeouts and readiness checks
- Give navigation a finite timeout and catch failures.
- Wait for a selector, a known text value or an application-specific state rather than adding arbitrary sleeps everywhere.
- Use a short delay only when an animation or delayed widget genuinely needs it.
- Record the URL, browser version, mode and failure reason in CI logs.
Control the environment
Set viewport dimensions, timezone, locale, user agent and permissions when those values affect the result. Use the same installed browser build locally and in CI. Keep credentials and cookies out of source control; load them from a secret store or an isolated browser context.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Handle dynamic and hostile pages
Pages may redirect, require authentication, show a consent dialog, challenge automation or render different content by geography. Verify that your use complies with the site’s terms and applicable law. For tests, seed deterministic data and disable third-party services where possible. For extraction, save a diagnostic screenshot and HTML when a selector is missing so you can distinguish a changed page from a timing failure.
Performance, reliability and cost considerations
Launching a browser is expensive compared with opening a single HTTP connection. For batches, keep one browser process alive and create a fresh page or context per job, then close it when the batch ends. Limit concurrency to the CPU and memory available; too many pages cause contention and make timeouts look random. Reuse a context only when sharing cookies is intentional.
Browser binaries consume disk space and must be updated with their automation library. In CI, cache the documented browser-download directory when your provider permits it, but invalidate the cache after library upgrades. Linux images need the libraries required by the selected browser; Playwright’s --with-deps option is the documented shortcut for Chromium.
Neither the Playwright nor Puppeteer documentation cited here provides a controlled head-to-head speed statistic. Measure your own navigation time, memory, failure rate and output fidelity with representative pages instead of relying on a universal ranking.
Troubleshooting
“Executable doesn’t exist” or browser cannot launch
With Playwright, run npx playwright install (or name the required engine). With Puppeteer, check whether installation scripts were blocked, then run npx puppeteer browsers install. If using puppeteer-core, provide the executable path or remote connection that your environment manages.
Rank #4
Linux reports missing shared libraries
Install the browser and operating-system dependencies with npx playwright install --with-deps chromium, or use a container image that already contains the required libraries. The exact packages vary by distribution.
CI output differs from local output
Compare the browser build, viewport, fonts, locale, timezone and selected headless mode. Playwright’s shell and newer Chromium headless modes are distinct; Puppeteer’s shell mode also differs from regular Chrome. Use the same mode in both environments and test pages that depend on rendering details.
The Node process hangs after the job
Ensure every successful and failing path reaches browser.close(). Put cleanup in finally, and avoid leaving pages, servers or event listeners open. A normal completion path in the official examples closes the browser.
Recommended Free Tools
Navigation times out
Confirm the URL is reachable from the runtime, inspect redirects and authentication, and decide whether your readiness condition is wrong. Increase the timeout only after identifying a legitimately slow operation. A page waiting forever on analytics traffic is a reason to prefer a selector or DOM-state check over a network-idle condition.
Best Value
Or skip the browser setup
If your goal is a clean website image or PDF rather than custom browser interaction, ScreenshotNeo provides a single screenshot API call and an MCP server for AI agents. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers report the page verdict and billing status.
Use the API from JavaScript or any HTTP client. The complete option set includes full-page capture with lazy images, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper sizes and page ranges, custom CSS and JavaScript, clicks before capture, hidden selectors, selector/delay/network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Common screenshot-API parameter names also work when migrating.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for authentication, parameters and response headers. An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Can I run headless automation without installing Chrome myself?
Yes. Puppeteer normally downloads a compatible Chrome when you install the puppeteer package, and Playwright downloads its supported browser builds through npx playwright install.
Should I use a browser context or a new browser for every URL?
For a batch, reuse one browser process and create isolated pages or contexts per job. Launch a separate browser only when process-level isolation is required.
Is headless output identical to visible Chrome?
Not always. Playwright shell and newer Chromium headless modes are distinct, and Puppeteer documents a fidelity difference for Chrome Headless Shell. Test the exact mode your deployment uses.
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.

