Playwright versus Puppeteer for Capturing JavaScript-Heavy Pages
Both Playwright and Puppeteer can capture JavaScript-rendered pages. Compare browser support, waiting, setup, and runnable screenshot examples to choose for your workflow.
Short answer: Both Playwright and Puppeteer can navigate to a JavaScript-rendered page and save a screenshot. Choose Playwright when you need Chromium, Firefox, and WebKit coverage or prefer its locator-based, test-oriented workflow. Choose Puppeteer for Chrome-centered automation or when its direct browser API fits your existing JavaScript code. Neither is a universal winner, and the available official documentation does not establish that one is faster or more reliable for screenshot capture.
A screenshot captures a particular browser state. For pages that fill in content after navigation, decide what “ready” means for the page you are capturing, then wait for that condition before taking the image. No single wait condition works for every site.
How to choose
| Need | Good fit | Why |
|---|---|---|
| Test Chromium, Firefox, and WebKit | Playwright | Playwright documents support for all three browser engines. Puppeteer documents Chrome and Firefox support from version 23 onward. Playwright browser support; Puppeteer FAQ. |
| Use locators, retrying assertions, and an integrated test runner | Playwright | Its recommended testing workflow includes auto-waiting and retry behavior. That can reduce explicit waits, but your screenshot still needs an appropriate page-specific readiness condition. Playwright migration guide. |
| Automate Chrome with a familiar direct browser API | Puppeteer | Puppeteer is a high-level JavaScript API for controlling Chrome or Firefox through DevTools Protocol or WebDriver BiDi. Puppeteer overview. |
| Manage the browser yourself or connect to a remote browser | puppeteer-core |
Unlike the standard puppeteer package, puppeteer-core does not download Chrome and is intended for separately managed browsers. Puppeteer installation guide. |
| Minimize environment surprises | Evaluate both against deployment setup | Playwright needs its matching browser binaries installed. Puppeteer normally downloads compatible Chrome, but package managers that block install scripts can interrupt that download. |
These recommendations follow documented capabilities, not a controlled performance comparison. The official sources reviewed do not benchmark both tools on the same JavaScript-heavy pages.
Capture a JavaScript-rendered page with Playwright
This Node.js example waits for a page-specific selector, then captures a full-page screenshot. Replace the URL and selector with values from the site you need to capture.
npm install playwright
npx playwright install chromium
// screenshot-playwright.mjs
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('main h1').waitFor({ state: 'visible', timeout: 15000 });
await page.screenshot({ path: 'playwright-shot.png', fullPage: true });
} finally {
await browser.close();
}
Run it with node screenshot-playwright.mjs. The selector is an example: choose an element that appears when the content you care about is ready. Playwright’s migration guide says explicit waits are often unnecessary in its test-oriented workflow, but capture scripts should still define a meaningful readiness condition for their target page.
For Firefox or WebKit, install the corresponding browser with the Playwright CLI and import the matching browser launcher. Playwright browser versions track Playwright releases; after upgrading the package, you may need to run the browser install command again. See the browser installation and version guide.
Capture a JavaScript-rendered page with Puppeteer
This equivalent Node.js example launches the browser installed by Puppeteer, waits for a page-specific selector, and saves the full page.
npm install puppeteer
// screenshot-puppeteer.mjs
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 1000 });
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('main h1', { visible: true, timeout: 15000 });
await page.screenshot({ path: 'puppeteer-shot.png', fullPage: true });
} finally {
await browser.close();
}
Run it with node screenshot-puppeteer.mjs. If your package manager blocks install scripts and Chrome was not downloaded, try npx puppeteer browsers install. If you use puppeteer-core, supply the path to your managed browser or connect using the appropriate remote browser configuration; that package does not install Chrome for you. See the Puppeteer installation guide.
Choose a readiness condition that matches the page
Navigation completing does not necessarily mean that useful content has rendered. A site can fetch data after the initial document loads, render on a timer, or keep network connections open while it updates. Pick a signal that corresponds to the content your screenshot should show.
- Wait for a selector: Use this when a known heading, result list, or component appears once the relevant content is ready. It is usually the clearest choice when you control or understand the page.
- Wait for a short delay: Use a delay only when the page has a known timing behavior and no reliable state signal. It can be slow on quick loads and still too short on slow ones.
- Wait for network idle: This can help on pages that settle after requests finish, but analytics, polling, streaming, or other persistent requests can prevent idle. Playwright’s migration sample includes network idle while noting that explicit waits are often unnecessary; it is not a universal capture rule.
- Wait for navigation state:
domcontentloadedor a load event describes document loading, not necessarily completion of client-rendered data. Treat it as an initial navigation boundary, then wait for the content state that matters.
If you own the application, expose a stable state or selector for screenshot automation. If you do not, inspect the page and select a visible element that reliably indicates the content is present. Avoid relying only on an arbitrary long timeout: it increases capture time without guaranteeing correctness.
Screenshot options and capture details
The examples use the common essentials: a viewport, a readiness condition, an output path, and a full-page capture. Both libraries also provide screenshot options for choices such as full-page capture and image type. Consult the respective API documentation for the exact options and version behavior: Playwright page screenshot API and Puppeteer page screenshot API.
- Viewport versus full page: A viewport screenshot captures what fits in the current browser view; full-page capture includes content beyond it. Very tall pages can produce large images or encounter browser and memory limits.
- Image format: PNG is useful when lossless output matters. JPEG is commonly used when smaller photographic output is more important. Check the chosen library’s current screenshot options for supported formats and quality controls.
- Viewport dimensions: Set width and height before capture. Responsive layouts can change substantially across viewport sizes.
- Device emulation: If mobile output matters, set the browser context or page emulation deliberately; a narrow viewport alone may not reproduce all device behavior.
- Element capture: When only one component matters, use the library’s element-level screenshot support rather than capturing a huge page and cropping it later.
Installation, browser versions, and deployment
Playwright installs browser binaries separately through its CLI, and the supported binaries are tied to Playwright releases. Keep the package and browser installation aligned in local development and deployment. When updating Playwright, rerun the documented browser installation step if the needed binary is missing.
The standard Puppeteer package normally downloads a compatible Chrome for Testing build during installation. A package manager or deployment policy that disables install scripts can prevent the download. The manual browser install command is npx puppeteer browsers install. Use puppeteer-core when your environment owns browser installation or supplies a remote browser, and explicitly configure that connection.
Browser downloads take disk space and deployment time. Puppeteer’s installation guide estimates Chrome downloads at approximately 170 MB on macOS, 282 MB on Linux, and 280 MB on Windows; these are installation-size estimates, not speed comparisons. Source: Puppeteer installation guide.
Performance, reliability, and cost
There is no controlled, same-page benchmark in the reviewed official sources that supports a general claim that Playwright or Puppeteer is faster. Capture time depends on the site, browser startup, readiness condition, network, and screenshot size. Compare both in your own environment with the same URLs, browser engine, viewport, readiness signal, and output format if performance determines your choice.
For reliability, pin compatible package and browser versions, install browsers during image or environment setup, and fail visibly when a readiness selector times out. Save diagnostic output such as the target URL and error details so a missing element, navigation failure, or browser launch issue can be distinguished. Sites that challenge automation or serve different content to automated browsers may not produce the expected page state; neither library’s documented browser coverage guarantees access to every site.
Both are open-source automation libraries, but operating them has infrastructure costs: browser storage, memory, CPU, network traffic, and engineering time to manage browser versions and failures. The cited documentation does not provide a per-screenshot price or comparative resource benchmark.
Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Browser executable missing in Playwright | The matching browser binary has not been installed, or the Playwright package changed. | Run npx playwright install chromium (or install the engine you use) in the environment that runs the script. |
| Puppeteer cannot find Chrome after installation | Install scripts may have been blocked, so the normal browser download did not run. | Run npx puppeteer browsers install, or configure the managed browser when using puppeteer-core. |
| Selector wait times out | The selector is wrong, the element never becomes visible, the page failed to load the data, or the chosen readiness condition does not match the site. | Inspect the page and selector, check navigation errors, and wait for an element that indicates the specific content is ready. Increase the timeout only if the page legitimately needs more time. |
| Screenshot is blank or missing content | The capture happened before client-rendered content appeared, or the target page returned an error or challenge. | Wait for a content-specific signal, inspect the rendered page and navigation outcome, and check whether the site presents a bot check. |
| Network-idle wait hangs | The page keeps requests active through polling, analytics, streaming, or other persistent connections. | Use a content selector or another page-specific readiness signal instead of requiring the network to become idle. |
| Full-page capture is unexpectedly large or fails | The page is unusually tall, has endless scrolling, or exceeds available browser resources. | Capture a relevant element or viewport, or use a deliberate scroll-and-capture strategy for pages that load content as you scroll. |
| Local capture works but deployment fails | The deployment image lacks browser dependencies or binaries, or runs under different install-script rules. | Install the required browser and system dependencies in the deployment environment and verify the launch configuration there. |
Or skip the browser setup
If you need a screenshot without maintaining a browser automation environment, ScreenshotNeo is a website screenshot API and MCP server. Its API returns an image or PDF from one GET request. The call below saves a WebP screenshot; see the ScreenshotNeo API documentation for options.
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}`);
ScreenshotNeo accepts cookie and consent banners like 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, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
FAQ
Which should I use for a one-off screenshot?
Use the library already supported by your project. If starting from scratch, pick based on browser coverage and setup needs: Playwright for WebKit coverage or its integrated test workflow, Puppeteer for Chrome-centered automation.
Does auto-waiting mean Playwright always captures after JavaScript is finished?
No. A page may update indefinitely or have content-specific readiness. Wait for the state your screenshot requires.
Is Puppeteer limited to Chrome?
Puppeteer documents Chrome and Firefox support from version 23 onward. Check its current browser compatibility documentation for the versions you use.
Which tool is faster?
The reviewed official sources do not establish a general speed winner. Measure your own pages and environment if speed is a deciding factor.
