October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
browser automation

How to Fix Puppeteer Screenshots That Save as Empty Image Files

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a Puppeteer screenshot file is empty or looks blank, first establish whether the browser rendered the page, whether the target had visible dimensions, and whether screenshot bytes were produced before they were written to disk. Navigate to the intended URL, wait for the application and its assets, check the target’s geometry, then await page.screenshot() and verify the output file. Do not close the page or browser until the screenshot promise resolves.

Start with a capture that exposes the failure

Use an explicit viewport, log the final URL and navigation status, wait for a meaningful page element, and save to an absolute path. This example captures the visible document and its full height after checking fonts and images:

import puppeteer from 'puppeteer';
import path from 'node:path';
import fs from 'node:fs/promises';

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 1 });

  const response = await page.goto('https://example.com', {
    waitUntil: 'networkidle2',
  });
  if (!response) throw new Error('Navigation returned no response');
  console.log({ status: response.status(), url: page.url(), title: await page.title(), cwd: process.cwd() });

  await page.waitForSelector('main', { visible: true });
  await page.evaluate(async () => {
    await document.fonts.ready;
    for (const image of document.images) {
      await image.decode();
      if (!image.naturalWidth) throw new Error(`Broken image: ${image.src}`);
    }
  });

  const box = await page.locator('main').boundingBox();
  if (!box || box.width <= 0 || box.height <= 0) {
    throw new Error('Target has no positive geometry');
  }

  const output = path.resolve(process.cwd(), 'artifacts/screenshot.png');
  await fs.mkdir(path.dirname(output), { recursive: true });
  await page.screenshot({ path: output, type: 'png', fullPage: true });
  const stat = await fs.stat(output);
  console.log({ output, bytes: stat.size, url: page.url() });
} finally {
  await browser.close();
}

Replace the example URL and the main selector with the page and content you actually need. The example deliberately throws when a required image is broken; for pages where some images are optional, record the failures instead of rejecting the whole capture. Puppeteer’s screenshot guide shows the basic navigate-then-screenshot pattern and examples using networkidle2 and an element screenshot after waiting for a selector.

Check whether the browser reached the page you intended

A screenshot can complete successfully even if the browser is showing a login page, an error document, a redirect destination, or about:blank. Log the navigation response status, page.url(), and the title before diagnosing image writing. A null navigation response is possible for about:blank; treat it deliberately rather than assuming navigation failed or succeeded normally. See Puppeteer’s Page API.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
SanDisk 128GB Ultra SDXC UHS-I Memory Card - 100MB/s, C10, U1, Full HD, SD Card - SDSDUNR-128G-GN6IN
  • Fast for better pictures and Full HD video. Full HD (1920x1080) video support may vary based upon host device, file attributes, and other factors
  • Great choice for compact to mid-range point-and-shoot cameras
  • From 32GB to 256GB(1) to store tons of pictures and even more Full HD video(2). (1)1GB=1,000,000,000 bytes Actual user storage less
  • Exceptional video recording performance with UHS Speed Class 1 (U1)(5) and Class 10 rating for Full HD video (1080p)(2). (5)UHS Speed Class 1 (U1) designates a performance option to support real time video recording with UHS enabled host devices
  • Quick transfer speeds up to 100MB/s. Up to 100MB/s[64GB-256GB; 90MB/s for 32GB] read speed; write speed lower Based on internal testing; performance may be lower depending on host device, usage conditions, and other factors 1MB=1,000,000 bytes

waitUntil: 'networkidle2' is a navigation heuristic, not proof that an application has rendered its final UI. It may be unsuitable for applications that keep network requests open, and it does not guarantee that client-side content, fonts, or images are ready. Prefer a page-specific readiness condition, such as a visible content selector or a bounded application-ready check:

await page.waitForSelector('[data-app-ready="true"]', {
  visible: true,
  timeout: 15000,
});

If the application has no ready marker, wait for an element that is meaningful for this capture, or use a bounded waitForFunction condition tied to the state you need. Avoid relying on an arbitrary long delay as the only readiness signal: it makes healthy pages slower and may still miss delayed content.

Know what “visible” checks

With waitForSelector(selector, { visible: true }), Puppeteer requires the element to exist and not be hidden by display: none or visibility: hidden. It is a useful first check, but you should still inspect the element’s dimensions when a screenshot is unexpectedly blank.

Confirm the target has usable geometry

Set a viewport explicitly before navigating or capturing. A page’s responsive layout can differ with viewport size and device scale, and an element capture cannot show a node with zero width or height. For an element capture, inspect the bounding box immediately before the screenshot:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
SANDISK 256GB Ultra SD Memory Card, Up to 150MB/s Read Speeds, UHS-I
  • Great choice for compact to mid-range point-and-shoot cameras
  • Quick transfer speeds up to 150MB/s (Up to 150MB/s read speed engineered with proprietary technology to reach speeds beyond UHS-I 104MB/s, requires compatible devices capable of reaching such speeds. Based on internal testing; performance may be lower depending on host device, interface, usage conditions and other factors. 1MB=1,000,000 bytes.)
  • Up to 256GB to store tons of pictures (1GB=1,000,000,000 bytes. Actual user storage less.)
  • Exceptional video recording performance with UHS Speed Class 1 (U1) Class 10 rating for Full HD video (1080p) (UHS Speed Class 1 (U1) designates a performance option designed to support real time video recording with UHS enabled host devices. See consumers speed page on SanDisk site. Full HD (1920x1080) video support may vary based upon host device, file attributes, and other factors. Visit the SanDisk Video Knowledge Base for more information.)
  • Compatible with SanDisk SD UHS-I card reader (sold separately)
const target = page.locator('main');
const box = await target.boundingBox();
if (!box || box.width <= 0 || box.height <= 0) {
  throw new Error('The target is missing, hidden, or has no visible size');
}
await target.screenshot({ path: 'main.png' });

A missing box can indicate that the selector matched nothing, the element is hidden, the node detached, or the relevant content is in a different frame. Re-query after navigation or page updates instead of reusing a stale element handle. If a frame is involved, make sure the selector is evaluated in the frame that contains the content. A browser-side click workaround does not fix a detached or dimensionless target.

Wait for fonts, images, and late content

Navigation completing does not mean every visual asset is decoded. For pages where these assets matter, wait for the font set and decode relevant images before capture:

await page.evaluate(async () => {
  await document.fonts.ready;
  await Promise.all([...document.images].map(image => image.decode()));
});

During diagnosis, inspect naturalWidth after decoding; a value of zero indicates a broken or not-yet-available image. If images are lazy-loaded farther down the page, a full-page screenshot captures the document’s existing height but does not itself scroll through the page to trigger infinite-scroll loading. Scroll or trigger the application’s loading behavior first, then wait for the newly added content and assets.

For a page that continuously adds content or polls in the background, a global network-idle condition may never be the right readiness signal. Wait for the particular content you need and apply a finite timeout so a genuine stall becomes an actionable error instead of an indefinite wait.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the screenshot scope and options deliberately

Capture method What it includes What to verify
Viewport screenshot The currently visible viewport. Viewport dimensions, responsive layout, and readiness of the visible content.
fullPage: true The full existing document height. Whether lazy or infinite-scroll content was loaded before capture; full-page mode does not load it for you.
Element screenshot The selected element. Selector match, visibility, positive dimensions, and whether the node remains attached.
clip A specified rectangular region. Use a positive rectangle; do not combine clip with fullPage.

If you already know the exact rectangle to capture, a clip can be more deterministic than relying on an element handle. For an element, Puppeteer’s documented pattern is to wait for the selector and call the element’s screenshot method. Consult the screenshot guide and ScreenshotOptions API for the current option definitions.

  • Output type: the screenshot type can be inferred from the file extension; PNG is the default. Use a matching extension and explicit type while debugging.
  • Quality: the quality option applies to JPEG and WebP, not PNG.
  • Transparency: omitBackground: true intentionally omits the page background. A transparent image can look blank in a viewer with a white or otherwise unsuitable display background.

Separate screenshot bytes from file-writing problems

The screenshot API returns image bytes when no base64 encoding is requested. Capture once without a path to determine whether Puppeteer produced data at all:

const bytes = await page.screenshot({ type: 'png' });
console.log('Screenshot bytes:', bytes.length);

If the byte count is nonzero but a saved file is empty or missing, focus on the output path and the code that handles the file. A relative path is resolved from the Node.js process’s current working directory, not necessarily the directory containing your script. Log process.cwd(), use path.resolve(), create the parent directory, and check the resulting file’s size after the awaited capture.

  • Confirm the process can write to the destination directory.
  • Check that a container volume or mounted directory points where you expect.
  • Ensure a later step is not truncating, overwriting, or moving the file.
  • Verify the screenshot call has settled before reading, uploading, or post-processing its output.

If the returned bytes are also empty or the image itself is visually blank, return to navigation, readiness, geometry, and asset checks; changing the filesystem path will not fix a page that rendered no visible content.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
SANDISK 64GB Extreme PRO SDXC UHS-I Memory Card - C10, U3, V30, 4K UHD, SD Card - SDSDXXU-064G-GN4IN
  • Save time with card offload speeds of up to 200MB/s powered by SanDisk QuickFlow Technology (Up to 200MB/s read speeds, engineered with proprietary technology to reach speeds beyond UHS-I 104MB/s, require compatible devices capable of reaching such speeds. Based on internal testing; performance may be lower depending upon host device, interface, usage conditions and other factors. 1MB=1,000,000 bytes. X = 150KB/sec. SanDisk QuickFlow Technology is only available for 64GB, 128GB, 256GB, 512GB and 1TB capacities. 1GB=1,000,000,000 bytes. 1TB=1,000,000,000,000 bytes. Actual user storage less.)
  • Pair with the SanDisk Professional PRO-READER SD and microSD to achieve maximum speeds (sold separately)
  • Shot speeds up to 90MB/s (Write speed up to 90MB/s. Based on internal testing; performance may be lower depending upon host device. 1MB=1,000,000 bytes. X = 150KB/sec.)
  • Perfect for shooting 4K UHD video and sequential burst mode photography (Full HD (1920x1080) and 4K UHD (3840 x 2160) video support may vary based upon host device, file attributes and other factors. See HD page on SanDisk site.)
  • UHS Speed Class 3 (U3) and Video Speed Class 30 (V30) (UHS Speed Class 3 designates a performance option designed to support 4K UHD video recording with enabled UHS host devices. UHS Video Speed Class 30 (V30), sustained video capture rate of 30MB/s, designates a performance option designed to support real-time video recording with UHS enabled host devices. See the SD Association’s official website.)
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep asynchronous work and page state under control

page.screenshot() is asynchronous: await it before using its result or closing the page or browser. Do not launch overlapping capture and page-mutation operations on the same page while diagnosing a failure. A navigation, resize, DOM change, or close during capture can make the result unreliable. Puppeteer documents the return value and behavior in its Page.screenshot API.

Keep browser cleanup in a finally block, as in the complete example, so errors do not leave Chromium running. The finally runs only after the awaited operations in the try have completed or thrown.

Troubleshoot by symptom

Symptom Likely cause Next check or fix
File is zero bytes or absent Screenshot call was not awaited, destination is wrong, parent directory is missing, or write access is unavailable. Await the call, log the absolute output path and current working directory, create the parent directory, and inspect the returned byte length and final file size.
Image exists but is all white Wrong URL or redirect, content not ready, target is hidden, or a transparent background is being shown on white. Log status, final URL, title, and target dimensions; wait for the application’s content; inspect omitBackground.
Only part of the page appears Viewport capture used when full-page was intended, or below-the-fold content was never loaded. Use fullPage: true for current document height; trigger lazy or infinite-scroll loading separately.
Element shot is blank or throws Selector did not match, node is hidden or detached, or geometry is zero. Wait for a visible selector, reacquire it after updates, and verify a positive bounding box.
Capture hangs waiting for network idle Long-lived requests or polling prevent the network-idle condition from becoming suitable. Use a bounded wait for an application-specific ready selector or state.
Text or imagery is missing Fonts or images had not decoded when capture began, or images are lazy-loaded. Wait for document.fonts.ready, decode relevant images, and trigger loading for off-screen content.

Or skip the browser setup

If you need an image or PDF without maintaining a Puppeteer browser flow, ScreenshotNeo is a website screenshot API and MCP server. One GET request takes a URL and returns a PNG, JPEG, WebP, or PDF. Its screenshot options include full-page capture with lazy images loaded, CSS-selector element capture, viewport/device presets, PDF settings, and custom waits.

For example, this cURL request saves a WebP screenshot of Stripe:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for setup and parameters. Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before capture; these steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers identifying the page verdict and billing status. An MCP server gives AI agents tools for screenshots, page information, and PDF capture. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for ScreenshotNeo’s free plan and get 1,000 screenshots a month with no card.

Frequently Asked Questions

Can Puppeteer save a screenshot as a string instead of an image file?

Yes. Request base64 encoding when you need a string; for normal binary output, the screenshot result is a Uint8Array.

Does a successful HTTP status guarantee that the screenshot will show the page?

No. A response status only describes the navigation response; client-side readiness, visible geometry, and loaded assets still need checking.

Quick Recap

Bestseller No. 1
SanDisk 128GB Ultra SDXC UHS-I Memory Card - 100MB/s, C10, U1, Full HD, SD Card - SDSDUNR-128G-GN6IN
SanDisk 128GB Ultra SDXC UHS-I Memory Card - 100MB/s, C10, U1, Full HD, SD Card - SDSDUNR-128G-GN6IN
Great choice for compact to mid-range point-and-shoot cameras
$32.49
Bestseller No. 2
SANDISK 256GB Ultra SD Memory Card, Up to 150MB/s Read Speeds, UHS-I
SANDISK 256GB Ultra SD Memory Card, Up to 150MB/s Read Speeds, UHS-I
Great choice for compact to mid-range point-and-shoot cameras; Up to 256GB to store tons of pictures (1GB=1,000,000,000 bytes. Actual user storage less.)
$61.95
SaleBestseller No. 3

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.