Fix Chrome Headless Screenshots That Cut Off Print-Style Web Pages
Choose the right Chrome output for a cropped page: viewport image, full-page image, or print-layout PDF. Includes CLI, Python, Node.js, and cURL options.
First decide what file you need: use a viewport screenshot for the visible screen area, a full-page screenshot for the entire document as an image, or a PDF for the browser’s print layout. Chrome’s --screenshot and --print-to-pdf flags produce different outputs. Making the viewport taller can capture a known section, but it is not a reliable general solution for pages of varying length. Chrome’s headless documentation describes the screenshot, viewport, PDF, and wait flags.
1. Identify the output you actually need
| Need | Use | Layout and sizing |
|---|---|---|
| Image of the visible browser area | --screenshot |
Screen layout; viewport dimensions |
| One image containing the whole document | DevTools Protocol full-page capture or an automation library’s full-page option | Screen layout; document dimensions |
| Document intended for printing | --print-to-pdf |
Print layout; paper size and pagination |
“Print-style” can mean either a page that looks like a printed document or simply a long page whose lower content is missing from a screenshot. For actual print styling, use PDF and inspect the page’s @media print and @page rules. For a PNG of all on-screen content, use full-page capture; print CSS does not fix a screenshot crop.
2. Quick fixes with Chrome’s command line
Capture a known viewport
If you want a screenshot of a specific, known-height region, set the viewport to match it:
chrome --headless --screenshot --window-size=1280,2000 https://example.com/
This captures the configured viewport. It does not measure arbitrary document length or guarantee a complete image of a long page. Check the output image dimensions and compare them with the viewport you requested.
Generate a print-layout PDF
chrome --headless --print-to-pdf --no-pdf-header-footer https://example.com/
The PDF flag uses Chrome’s print pipeline. The header/footer option removes Chrome’s PDF header and footer furniture; it does not affect screenshot cropping. The current flag is --no-pdf-header-footer; older Chrome versions may require the former --print-to-pdf-no-header flag. Check chrome --help for the flags supported by your installed version.
Wait before capture
chrome --headless --screenshot --timeout=5000 https://example.com/
--timeout is a maximum wait in milliseconds, not proof that the application has finished rendering. Chrome may capture when the timeout is reached even if the page is still loading. For time-dependent JavaScript, --virtual-time-budget provides a separate virtual-time control. Use a page-specific readiness condition in automation when you know which content must be present.
3. Capture the full document as an image
A viewport screenshot and a full-page screenshot are different operations. For the latter, use the Chrome DevTools Protocol’s Page.captureScreenshot with captureBeyondViewport: true, or a browser automation wrapper that exposes full-page capture. Chromium’s full-page implementation measures the page dimensions, sets a clip covering that extent, and enables beyond-viewport capture. See the DevTools Protocol method and Chromium’s headless protocol handler; these are living references, so behavior can change with Chrome versions.
For an automation library, check that its full-page setting maps to a document-sized capture rather than simply enlarging the viewport. Wait for the page’s required content before taking the image: for example, an application-ready selector, a particular image, or fonts the layout depends on. A fixed sleep can be useful for a known animation delay, but it is not a general readiness guarantee.
When print layout must become an image
If the page’s print CSS is required but the deliverable must be raster, render a PDF using the print pipeline and rasterize that PDF in a separate step, or use an automation API that lets you select print media before capture. Choose this deliberately and verify the output: PDF pagination and a single tall PNG have different page-break behavior and dimensions.
4. A repeatable troubleshooting sequence
- Name the expected artifact. Decide among viewport PNG, full-document PNG, or print-layout PDF before changing dimensions.
- Check the actual image dimensions. For viewport capture, compare PNG dimensions against
--window-size. If only the viewport was captured, content below it is expected to be absent. - Switch to full-page capture for below-the-fold content. Use a beyond-viewport DevTools operation or a wrapper’s verified full-page option.
- Wait for the content that matters. Confirm the target element, image, fonts, or application-ready state exists before capture. Treat timeout as an upper bound, not a readiness signal.
- Inspect print rules only for print output. Look for
display: none, changed dimensions, and page-break rules in@media printand@page. - Check for an oversized document. Very tall pages can exceed browser image limits. Try capturing sections or using PDF, then verify the resulting dimensions and file. Record the Chrome version because implementation limits can vary.
5. Common errors and their fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Bottom of page is missing | A viewport screenshot was expected to include the whole document. | Use full-page capture with beyond-viewport enabled. Increase viewport height only when the desired region is known. |
| Screenshot looks different from print preview | Screenshot uses screen rendering; PDF uses print rendering. | Choose PDF for print layout. If raster output is mandatory, use a deliberate print-render-then-rasterize workflow. |
| Images or content are missing intermittently | Capture happened before asynchronous rendering completed. | Wait for the specific content or application readiness signal. A longer timeout alone does not guarantee readiness. |
| PDF includes unwanted URL, date, or page numbers | Chrome’s print header/footer furniture is enabled. | Use --no-pdf-header-footer, or the older supported flag on an older Chrome build. |
| Full-page screenshot fails with “Page is too large” | The document’s image dimensions exceed a browser implementation limit. | Capture sections, reduce scale or dimensions where appropriate, or use a paginated PDF. Verify the final artifact and Chrome version. |
| Output has the wrong dimensions | Viewport dimensions were mistaken for image scale, or full-page dimensions were assumed. | Inspect the produced file’s pixel dimensions; distinguish CSS viewport size from document height and output scaling. |
6. Reliability, performance, and cost considerations
Full-page capture creates a larger image as document height grows, which can increase rendering time, memory use, and output size. Extremely long pages may be rejected by Chrome. If the consumer can accept pages, PDF pagination is often a better fit; if it needs a single raster image, consider section captures and assemble them only if preserving seams and sticky elements is manageable.
For repeatable captures, pin or record the Chrome version, viewport, device scale, media mode, and readiness condition. Web pages change, so verify important outputs after browser upgrades and when target page layouts change. A timeout prevents waiting forever, but it does not by itself make the result reliable.
Running Chrome yourself has infrastructure and maintenance costs: browser installation, upgrades, concurrency, storage, and handling pages that never become ready. For occasional captures, the CLI may be enough. For recurring workloads, compare that operational work with a hosted screenshot API and its billing behavior.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF. Here is the cURL form:
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 API documentation for supported options and request details. The same basic request in Python and Node.js:
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 before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; 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 for Claude, Cursor, and other MCP clients. 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, no card required.
8. Frequently asked questions
Does a taller --window-size take a full-page screenshot?
It enlarges the viewport used for the CLI screenshot. It is suitable for a known region, but it does not provide a robust document-sized capture when page length varies.
Does --timeout wait until all JavaScript finishes?
No. It sets a maximum wait before capture, even if loading continues. Wait for a condition tied to the content your capture requires.
Can I use print CSS and still get one long image?
Print CSS is intended for print rendering and commonly paginates content. If you need its styling in a raster image, select print media deliberately or render a PDF and rasterize it, then validate the result.
Which Chrome version should I use for oversized pages?
There is no single safe height to assume from these references. Verify against your installed Chrome or Chromium version and test the actual target page, since size rejection is implementation behavior.


