ScreenshotNeo

BlogHow-to

How to Capture a Website Screenshot when Chrome DevTools Hangs

Capture a rendered page from a separate headless Chrome process, use Puppeteer for repeatable jobs, or switch to a screenshot API when DevTools hangs.

By the ScreenshotNeo team4 October 20267 min read

When Chrome DevTools hangs, capture the page from a separate Chrome or Chromium process instead of using the DevTools menus. For a one-off image, run chrome --headless --screenshot --window-size=1280,900 https://example.com/ in a terminal. Chrome writes screenshot.png to the terminal’s current working directory. This is a capture workaround; it does not diagnose or repair the frozen DevTools window.

1. Capture a screenshot from the command line

Open a terminal and run:

chrome --headless --screenshot --window-size=1280,900 https://example.com/

Replace chrome with the executable name or full path on your system, and replace the URL with the page you need. Adjust the viewport dimensions to suit the capture. The official Chrome example also combines --screenshot with --window-size; its example viewport is 412 by 892 pixels. The command writes screenshot.png in the current working directory, so check the directory from which you ran it.

Find the Chrome executable

If the command reports that Chrome cannot be found, use the executable installed on your system: it may be named chromium, chromium-browser, or google-chrome, or require a full path. For example, substitute the correct name in the command rather than assuming every operating system uses chrome. If you do not know the path, locate the installed browser using your operating system’s app or package tools.

Capture a specific viewport

--window-size=WIDTH,HEIGHT sets the viewport used for the capture. It does not mean that the screenshot automatically covers the entire document. If the page is longer than the viewport, the command-line workflow described here produces a viewport capture; use browser automation or a screenshot service with a full-page option when you need the complete page.

2. Bound the wait on pages that keep loading

A page may keep loading because of long-running network activity or scripts. Put an upper bound on the capture delay with --timeout:

chrome --headless --screenshot --timeout=5000 https://example.com/

The value is in milliseconds. Chrome captures after the maximum wait even if loading has not settled. A shorter timeout returns sooner, but late-loading images, fonts, or other content may be missing. Increase it when important content appears late, and inspect the saved image to confirm the page state you needed.

Pages that depend on timers

If a page changes after a timer and you need to capture a particular elapsed state, Chrome documents --virtual-time-budget as a way to fast-forward time-dependent page code. For example:

chrome --headless --screenshot --virtual-time-budget=5000 https://example.com/

The appropriate budget depends on the page’s behavior. It is not a guarantee that every animation, network request, or application state will finish as intended; check the result. You can also combine a timeout with a virtual time budget when you need to constrain the wait and advance page timers.

Need a PDF instead of an image?

Chrome’s --print-to-pdf option creates a PDF artifact rather than a PNG screenshot:

chrome --headless --print-to-pdf https://example.com/

Choose it when a document-like output is acceptable. It is not a substitute when the requirement is an image file.

3. Automate capture with Puppeteer and Chrome DevTools Protocol

For repeatable captures, use the Chrome DevTools Protocol (CDP). Its Page.captureScreenshot command captures the rendered page through a browser connection. Chromium documents remote debugging as a way to connect to Headless Chrome, and documents Puppeteer as a Node.js client option. This route still needs a running browser process and a client able to connect; it will not help if the browser itself cannot start or respond.

Start a separate headless browser endpoint

Run a separate Chrome process with a remote debugging port and a clean temporary profile directory. Use a profile directory that is not already in use by your regular browser:

chrome --headless --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-screenshot-profile

Keep that process running while the automation connects. If Chrome is installed under a different executable name or path, substitute it here too. A separate profile avoids asking the hung DevTools session to perform the capture; it does not guarantee recovery if the browser process or local environment has a separate problem.

Runnable Puppeteer example

Install Puppeteer in a Node.js project with npm install puppeteer. The following script launches its own headless browser, sets a viewport, navigates to the page, waits for the load event, and saves a PNG:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 900 });
  await page.goto('https://example.com/', {
    waitUntil: 'load',
    timeout: 30000,
  });
  await page.screenshot({ path: 'screenshot.png' });
} finally {
  await browser.close();
}

Save it as capture.mjs and run node capture.mjs. If the application keeps network connections open, waiting for the page’s full network idle state can time out; use an appropriate navigation condition and an explicit wait for the content you need. For a full-page image, change the screenshot call to await page.screenshot({ path: 'screenshot.png', fullPage: true });. Puppeteer controls the browser and exposes screenshot capture through the browser automation workflow; the underlying protocol command is Page.captureScreenshot.

4. Choose the route that fits the capture

Route Best for Tradeoff
Chrome --headless --screenshot One-off terminal capture Uses a viewport; output goes to the current working directory.
Chrome with --timeout or --virtual-time-budget Pages that load slowly or change after timers Capture timing determines which content appears.
CDP with Puppeteer Repeatable scripts and full-page captures Needs a running browser and automation client.
--print-to-pdf Document-like output Produces a PDF, not an image.

5. Troubleshoot common failures

Symptom Likely cause What to try
chrome: command not found or equivalent The executable is not on the terminal’s PATH, or it has another name. Use the installed Chrome/Chromium executable name or its full path.
The image is saved somewhere unexpected The command writes to the current working directory. Check the directory shown by your terminal, or run the command from the directory where you want the output.
The screenshot is blank or lacks late content The page had not rendered the needed content when capture occurred, or content appears after a timer. Try a longer --timeout, an appropriate --virtual-time-budget, or an automation script that waits for the relevant selector.
The command waits too long Navigation or page activity may not settle. Set --timeout to bound capture time, understanding that late content can be omitted.
The Puppeteer script times out on navigation The page may keep connections open or never reach the chosen navigation condition. Use a navigation condition suited to the page and wait explicitly for the element or state you need.
Remote debugging connection fails The browser endpoint is not running, the port differs, or the client cannot reach it. Confirm Chrome started with the expected remote debugging port and keep it running while the client connects.
Old --headless=old instructions do not work As of Chrome milestone 132, the old Headless implementation is no longer part of the Chrome binary; the flag has no effect. Use current Headless Chrome options. Chromium directs users who need old Headless to chrome-headless-shell.

A DevTools hang can have different causes, and these capture routes do not identify the cause. If a separate headless process also fails, collect the operating system, Chrome version, executable path, exact command, and terminal error before investigating further.

6. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request can return an image or PDF without setting up a local headless browser. See the API documentation for the available parameters.

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}`);

Cookie banners are accepted and removed before the shot, along with known newsletter popups and chat widgets. Bot checks, blank pages, failed loads, timeouts, and cache hits are never billed, and response headers report the page verdict and billing status. An MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card required.

Frequently asked questions

Does a headless screenshot require DevTools to be open?

No. The command-line capture starts a headless browser process and does not require clicking the DevTools UI.

Does --dump-dom save a screenshot?

No. It serializes the DOM after parsing and script execution; use --screenshot for an image.

Will headless mode fix a hung Chrome installation?

No such guarantee follows from these capture methods. They provide an alternate route when a separate browser process can run. If the browser itself hangs or crashes, investigate that failure separately.

Where does Chrome put the default screenshot?

In the current working directory, as screenshot.png.

Sources