ScreenshotNeo

BlogHow-to

How to Capture a Webpage Screenshot with Browser Extensions Disabled in Puppeteer

Puppeteer disables browser extensions by default. Learn how to capture a page, choose screenshot options, handle launch and loading issues, and save the result.

By the ScreenshotNeo team4 October 20267 min read

Direct answer: Puppeteer disables browser extensions by default. Launch it without changing its default arguments, navigate to the page, and call page.screenshot(). Do not enable extensions or remove Puppeteer’s default --disable-extensions launch argument.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'page.png', fullPage: true });
} finally {
  await browser.close();
}

This uses Puppeteer’s default headless mode. The example saves a full-page PNG. Use fullPage: false or omit it for the current viewport. Puppeteer’s official troubleshooting guide documents that it passes --disable-extensions by default. Puppeteer troubleshooting · Screenshot guide

1. Install Puppeteer and run the capture

For a new Node.js project, install Puppeteer, which downloads a compatible browser as part of its standard setup:

npm install puppeteer

Save this as screenshot.mjs and run node screenshot.mjs:

import puppeteer from 'puppeteer';

const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch();

try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
  await page.goto(url, { waitUntil: 'networkidle2', timeout: 45_000 });
  await page.screenshot({ path: 'page.png', fullPage: true });
  console.log('Saved page.png');
} finally {
  await browser.close();
}

Extensions remain disabled because the launch call preserves Puppeteer’s default arguments. The finally block closes the browser even if navigation or capture throws an error.

2. Choose when the page is ready

The screenshot captures the rendered page at the time page.screenshot() runs. Picking a navigation wait condition is part of capture correctness:

  • waitUntil: 'load' waits for the load event, including dependent resources. It may be a suitable choice for conventional pages.
  • waitUntil: 'domcontentloaded' waits for HTML parsing and deferred scripts, but not every image or later asynchronous update.
  • waitUntil: 'networkidle2' waits for a period with at most two network connections. It appears in Puppeteer’s screenshot guide example, but analytics, polling, or long-lived requests can make network-idle waits unreliable for some sites.

For content rendered after navigation, wait for a page-specific signal rather than assuming navigation alone means the final content is visible:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('main article', { visible: true, timeout: 15_000 });
await page.screenshot({ path: 'article.png', fullPage: true });

A fixed delay can help diagnose a timing issue, but it is less reliable than waiting for a selector or other known condition:

await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await new Promise(resolve => setTimeout(resolve, 1500));
await page.screenshot({ path: 'page.png' });

3. Control the screenshot output

Puppeteer’s screenshot API supports viewport captures, full-page captures, clipped regions, and element screenshots. The documented defaults include fullPage: false and type: 'png'. See the ScreenshotOptions reference.

Need Option or method Example
Current viewport only Omit fullPage or set it false { path: 'viewport.png' }
Entire document fullPage: true { path: 'full.png', fullPage: true }
Specific rectangle clip { clip: { x: 0, y: 0, width: 600, height: 400 } }
One element Find its handle, then call element.screenshot() Shown below
JPEG or WebP type { type: 'jpeg', quality: 85 }
Save to a file path { path: 'page.png' }

When path is provided and type is omitted, the filename extension is used to infer the image type. Specify type explicitly when you need a particular format independent of the filename.

Viewport and full-page PNG

await page.setViewport({ width: 1280, height: 800 });
await page.screenshot({ path: 'viewport.png' });
await page.screenshot({ path: 'whole-page.png', fullPage: true });

JPEG or WebP

await page.screenshot({ path: 'page.jpg', type: 'jpeg', quality: 85 });
await page.screenshot({ path: 'page.webp', type: 'webp', quality: 85 });

Quality is relevant to lossy image formats. PNG is lossless and does not use the JPEG-style quality setting.

Clip a rectangular area

await page.screenshot({
  path: 'region.png',
  clip: { x: 100, y: 80, width: 700, height: 450 }
});

The clip coordinates and dimensions are CSS pixels relative to the page. Ensure the requested dimensions are positive and that the region is meaningful for the loaded page.

Capture a single element

const card = await page.waitForSelector('.product-card', { visible: true });
if (!card) throw new Error('Product card was not found');
await card.screenshot({ path: 'product-card.png' });

Element screenshots are useful when surrounding content is irrelevant. The selector must match an element that exists and can be brought into view.

4. Keep extensions disabled in launch configuration

The simplest and safest configuration for this task is:

const browser = await puppeteer.launch();

Puppeteer’s launch defaults include --disable-extensions. Avoid setting enableExtensions: true, which enables extensions, and avoid filtering default arguments in a way that removes --disable-extensions.

args adds browser command-line arguments; it is not needed to disable extensions in the usual Puppeteer setup. ignoreDefaultArgs can filter or ignore Puppeteer’s defaults, but the launch options documentation cautions that defaults should generally be retained. Consult the LaunchOptions reference before changing them.

When a managed Chrome policy requires extensions

Puppeteer’s troubleshooting documentation describes an exception: enterprise Chrome policies that require extensions can conflict with its default disable flag and cause launch failure. The documented workaround is enableExtensions: true. That changes extension behavior, so it is not the configuration for a capture that must keep extensions disabled. If policy enforcement is present, resolve the policy or use a browser environment where extensions are not mandatory.

5. Headless and headful modes

Puppeteer v25.12.0 documents headless: true as the default. Headless is appropriate for ordinary automated screenshots and does not require a visible browser window.

// Default headless Chrome
const browser = await puppeteer.launch();

// Visible browser, useful when diagnosing rendering or navigation
const visibleBrowser = await puppeteer.launch({ headless: false });

// Older chrome-headless-shell mode
const shellBrowser = await puppeteer.launch({ headless: 'shell' });

The official headless guide notes that chrome-headless-shell does not completely match regular Chrome, though it may be more performant for automation that does not need the full feature set. Choose based on rendering similarity, debugging visibility, and your workflow. These mode details and defaults are version-sensitive; check the documentation matching your installed Puppeteer release.

6. Common errors and fixes

Symptom Likely cause Fix
Browser fails to launch where managed extensions are enforced Enterprise Chrome policy conflicts with Puppeteer’s default --disable-extensions. Check the policy. The documented enableExtensions: true workaround changes the requirement; for extensions-disabled captures, use an environment without the enforced policy.
Screenshot is blank or missing late content Capture ran before client-side rendering or image loading completed. Wait for a meaningful selector, a known application-ready condition, or a carefully chosen delay; inspect the page in headful mode if needed.
Navigation times out The site has slow resources, ongoing requests, or an unreachable URL. Check the URL and network access, set a suitable timeout, and select a wait condition that matches the page. Do not assume network idle will occur on every site.
waitForSelector times out The selector is wrong, hidden, or the content never rendered. Verify the selector and page state; remove visible: true if visibility is not required, or wait for the actual content signal.
Output format differs from expectation The file extension or explicit type selected another format. Set both path and type consistently, such as page.webp and type: 'webp'.
Screenshot process hangs or consumes resources Browser was not closed after an error or many jobs share a browser without limits. Close it in finally, limit concurrent pages, and give each navigation and selector wait a timeout.
Default browser arguments unexpectedly changed ignoreDefaultArgs filtered out required defaults. Remove the override or verify the exact argument list; preserve --disable-extensions.

7. Performance, reliability, and cost

Browser startup and page rendering are the main work in a local Puppeteer capture. Reuse a browser process for a controlled batch of pages when startup overhead matters, but close every page and the browser when finished. Keep concurrency bounded to avoid exhausting memory and CPU. Full-page captures of very long documents can require more resources than viewport captures.

For reliable output, set explicit viewport dimensions, use a page-specific readiness condition, set navigation and selector timeouts, and always close the browser in a finally block. Results can vary with the target site’s network behavior, dynamic content, and installed browser version. No fixed performance figure applies across sites and environments.

Puppeteer is an open-source browser automation library; the browser work runs in the environment you provision, so account for your compute, memory, and operational costs. If you do not want to manage browser installation, rendering, and capture cleanup, a screenshot API can handle the request and return the image.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a screenshot or PDF. 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://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card required.

9. FAQ

Does Puppeteer disable extensions automatically?

Yes. Puppeteer’s troubleshooting documentation says it passes --disable-extensions by default.

Should I add --disable-extensions to args anyway?

Usually no. The default launch arguments already provide it. Preserve defaults unless you have a specific, documented reason to change them.

Does fullPage: true change extension behavior?

No. It changes screenshot coverage from the viewport to the full document; extension handling is determined by browser launch configuration.

Can I capture a page that requires an extension?

That conflicts with the extensions-disabled requirement. Puppeteer documents an extension-enabling workaround for policy-enforced extensions, but using it means the browser is no longer running with extensions disabled.

Which Puppeteer version does this guide describe?

The cited API and guide pages identify v25.12.0. Check the docs matching your installed version for version-specific defaults and options.