ScreenshotNeo

BlogHow-to

How to Fix Low-Resolution Screenshots from Chrome Headless

Diagnose small, blurry, or incomplete Chrome Headless screenshots by checking viewport size, pixel scale, full-page capture, and page readiness.

By the ScreenshotNeo team4 October 20269 min read

If a Chrome Headless screenshot looks low-resolution, first identify which dimension is wrong: the page’s CSS viewport, the PNG’s pixel dimensions, or the amount of page content captured. These are separate problems and need separate fixes. For a basic command-line screenshot, set --window-size=WIDTH,HEIGHT alongside --screenshot, then inspect the resulting PNG. If the viewport is right but the PNG has fewer pixels than expected, check the headless screen scale factor. If the PNG dimensions are right but content below the fold is missing, use a full-page capture method.

Chrome’s [command-line reference](https://developer.chrome.com/docs/automation-and-testing/headless-cli/) shows --screenshot with --window-size=412,892. Chrome’s [virtual-screen documentation](https://developer.chrome.com/docs/automation-and-testing/headless-screen-config/) explains that headless screen size and scale can be configured independently of physical displays, and that its newer screen configuration support is available in stable Chrome starting with version 142.

1. Diagnose what “low resolution” means

Before changing flags, write down the capture method, Chrome version, intended CSS viewport, desired PNG dimensions, and actual PNG dimensions. Then compare the three cases below.

What you see Likely issue What to inspect
The page layout is too narrow or short. Viewport or window dimensions. --window-size or the automation library’s viewport settings.
The layout is right, but the PNG has fewer pixels than expected. Pixel scale or headless screen configuration. Device scale factor and, on Chrome 142+, virtual screen settings.
The screenshot has the expected dimensions, but the page is cut off below the fold. Viewport capture instead of full-page capture. Use an automation API’s full-page option or another full-document capture method.
Images, fonts, or other page content are missing. The page was captured before rendering or loading finished. Capture timing, page readiness, and timeout settings.

A larger viewport is not automatically a higher pixel density, and higher pixel density does not make a viewport screenshot include the entire document. Keep those questions separate while debugging.

2. Set the CLI capture dimensions

For a basic viewport screenshot, provide the width and height explicitly. Replace the URL and dimensions with the values your page needs:

chrome --headless --screenshot=shot.png --window-size=1440,900 https://example.com/

Chrome documents this pairing as the way to set screenshot window dimensions. Check the generated PNG’s pixel dimensions using an image viewer or image-inspection tool; do not infer them from the command alone. If the command writes a default file instead of your chosen name on the Chrome build you use, keep --screenshot and inspect the actual output filename.

For a page that needs time to load or run scripts, add a finite timeout:

chrome --headless --screenshot=shot.png --window-size=1440,900 --timeout=10000 https://example.com/

--timeout sets the maximum wait in milliseconds before Chrome captures, even if the page is still loading. It can help with readiness; it does not increase pixel density. Chrome also documents --virtual-time-budget for time-dependent scripts. Use it when you specifically need to give virtual time to page activity, not as a resolution setting. See the [Chrome CLI reference](https://developer.chrome.com/docs/automation-and-testing/headless-cli/) for flag behavior and examples.

3. Check headless screen scale when pixel dimensions are too small

If the CSS layout matches your target but the saved PNG still has too few pixels, inspect the device scale factor or headless screen scale. Headless Chrome uses a configurable virtual screen that is independent of the physical monitor attached to the machine. On stable Chrome 142 and later, the --screen-info switch configures screen properties such as size and scale factor. Check your installed Chrome version before relying on this option.

chrome --version

Use Chrome’s [virtual-screen configuration guide](https://developer.chrome.com/docs/automation-and-testing/headless-screen-config/) for the current --screen-info syntax and its supported properties. Do not assume a physical high-DPI monitor changes headless output. If you use Puppeteer, inspect the version-specific viewport and device emulation options in your installed version; Chrome’s documentation says Puppeteer supports the newer virtual-screen capabilities.

For library-based automation, distinguish the page viewport from the screen scale. A device scale factor changes the relation between CSS pixels and output pixels; it is not a substitute for choosing the intended CSS layout width. Configure the viewport and scale deliberately, then compare both the page layout and the saved image dimensions.

4. Use a full-page capture for content below the fold

If the image dimensions are correct but only the visible viewport appears, you have a full-page capture problem. Raising --window-size may show more content in one viewport, but it is not a reliable way to capture a document of arbitrary height. Chrome’s older [Headless shell documentation](https://developer.chrome.com/docs/automation-and-testing/headless-chrome-shell/) notes that full-page screenshots require additional handling.

With Puppeteer, a full-page screenshot can be captured with the fullPage option. This runnable Node.js example sets the CSS viewport, waits for page navigation, and saves the whole document:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 2 });
  await page.goto('https://example.com/', { waitUntil: 'networkidle2', timeout: 60000 });
  await page.screenshot({ path: 'full-page.png', fullPage: true });
} finally {
  await browser.close();
}

Install Puppeteer in your project with npm install puppeteer. Confirm the installed library’s screenshot option semantics if you use a different version or automation package. Very long pages can produce large images and use substantial memory; capture a selected element or split the task when a single full-page bitmap is impractical.

5. Wait for the content you need

A screenshot can have the right dimensions and still appear incomplete because the page had not finished rendering. A fixed timeout is simple, but it may wait longer than needed or still miss content whose load time varies. In automation, prefer waiting for the specific selector or state that indicates the content is ready when you know what to expect.

await page.goto('https://example.com/', { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForSelector('.report-ready', { timeout: 15000 });
await page.screenshot({ path: 'ready.png' });

Replace .report-ready with a selector that exists only when the relevant page content is available. For CLI screenshots, Chrome’s --timeout gives the page a maximum wait; it does not guarantee that a particular asynchronous component is ready. If scripts depend on elapsed time, Chrome’s --virtual-time-budget may be relevant. Neither option changes the image’s pixel scale.

6. Verify the result in a repeatable sequence

  1. Record the Chrome version and whether capture uses the CLI, Puppeteer, or another library.
  2. Write down the target CSS viewport and desired PNG pixel dimensions.
  3. Set the viewport explicitly; for CLI, pair --screenshot with --window-size=WIDTH,HEIGHT.
  4. Inspect the saved PNG’s actual width and height.
  5. If layout size is right but output pixels are short, inspect device scale and the headless screen configuration supported by your Chrome version.
  6. If the PNG is correctly sized but content is missing below the fold, use a full-page capture feature.
  7. If content within the captured area is absent, wait for the relevant content or configure a suitable capture timeout.
  8. Repeat the capture with the same URL, viewport, scale, and readiness condition to see whether the issue is consistent.

7. Common errors and fixes

Symptom Cause Fix
PNG is smaller than the target width and height. The capture window or viewport was not set to the intended dimensions. Set --window-size=WIDTH,HEIGHT in CLI capture or the corresponding viewport in your automation library; inspect the saved file.
CSS layout looks correct, but the PNG has fewer pixels than expected. Pixel scale or screen configuration is too low for the target output. Check device scale settings. On Chrome 142+, consult the --screen-info guide and verify that the installed version supports it.
Bottom of the page is missing. The capture only covers the viewport. Use a full-page screenshot API or another full-document method; increasing scale does not capture more document content.
Images or dynamic content are missing. Capture happened before those resources or scripts were ready. Wait for a meaningful selector or page state, or increase the capture wait within a reasonable limit.
A Chrome screen flag is rejected. The installed Chrome version does not support that flag or syntax. Run chrome --version and follow documentation for that version. Virtual screen configuration is documented as stable beginning with Chrome 142.
Full-page capture is slow or memory-heavy. The document is very tall or contains large assets. Capture only the required element or content range, or split the capture into sections where the tool permits.
Result differs between runs. Page readiness, animation, live data, or resource loading varies. Wait for a stable page condition and keep viewport, scale, URL, and timing consistent.

8. Performance, reliability, and cost

Larger output dimensions and full-page images require more rendering work and produce more image data. Higher pixel scale can increase both image dimensions and memory use. Set only the viewport and scale you need, and avoid capturing a full document when a specific element is sufficient.

For more repeatable results, fix the browser version and capture settings in the environment that runs your job. Use an explicit viewport, scale, and readiness condition; set timeouts so a stalled page does not wait indefinitely. A timeout is a limit on waiting, not proof that the page is ready. If results vary, compare the actual PNG dimensions and page contents between runs before changing scale.

Running Chrome yourself has infrastructure costs that depend on your environment and workload; this research provides no benchmark or universal per-capture cost. If you want a managed screenshot API instead of maintaining browser setup, ScreenshotNeo is a website screenshot API and MCP server from [ScreenshotNeo](https://screenshotneo.com). Its response identifies page verdict and billing status; only clean shots are billed, while bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing.

Or skip the browser setup

Send one GET request to capture a URL. Replace YOUR_API_KEY with your key. See the [ScreenshotNeo API documentation](https://screenshotneo.com/docs/) for request 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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
  • Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
  • Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are never billed.
  • An MCP server gives AI agents tools for screenshots, page info, and PDF capture.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for 1,000 free screenshots a month with no card.

FAQ

Does a bigger window always make a sharper screenshot?

No. Window or viewport dimensions control the capture area and page layout; pixel scale is a separate setting.

Will a higher device scale factor capture the whole page?

No. It affects pixel density. Use a full-page capture method to include content below the viewport.

Does waiting longer improve resolution?

No. Waiting can allow content to render, but it does not increase output pixel dimensions.

Can I use Chrome’s virtual screen flags on every version?

No. Chrome documents stable support for the newer virtual screen configuration beginning with version 142. Check your installed version and the current guide before using it.

Is the physical monitor resolution relevant to headless Chrome?

Headless virtual screens are configurable independently of physical displays, so inspect the virtual screen configuration rather than assuming the host monitor sets screenshot scale.