ScreenshotNeo

BlogHow-to

How to Generate JPEG Screenshots of HTML Pages with Puppeteer

Use Puppeteer’s screenshot API to save HTML pages as JPEG, tune quality, capture full pages or regions, and handle common rendering issues.

By the ScreenshotNeo team4 October 20267 min read

Use Puppeteer’s page.screenshot() method with type: 'jpeg' and a filename ending in .jpg. Set quality from 0 to 100 to control JPEG encoding, and use fullPage: true when you need the whole document rather than just the viewport. Puppeteer can also capture a clipped region or a single element.

The example below uses Node.js and Puppeteer. It navigates to a page, waits for a common network-idle condition, saves a full-page JPEG, and closes the browser even if capture fails. The wait condition is only a starting point: applications can render important content after network activity settles, so choose a readiness condition that matches the page.

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.jpg',
    type: 'jpeg',
    quality: 85,
    fullPage: true,
  });
} finally {
  await browser.close();
}

This combines documented Puppeteer options; the chosen quality is an example, not a universal recommendation. Check the resulting image at the size and compression level your application needs.

1. Install Puppeteer and run the capture

In a new Node.js project, install Puppeteer:

npm install puppeteer

Save the capture code as screenshot.mjs and run it with Node.js:

node screenshot.mjs

Puppeteer’s package includes a browser installation workflow. If your environment supplies its own compatible Chrome or Chromium, configure the launch options for that environment and make sure the browser executable and its system dependencies are available.

The essential sequence is: launch a browser, create a page, navigate to the target, wait for the state you want to capture, take the screenshot, and close the browser. See the official Puppeteer screenshots guide and ScreenshotOptions reference.

2. Choose format, quality, and capture area

Option What it controls When to use it
type: 'jpeg' Encodes the screenshot as JPEG. Use when your consumer expects JPEG or you want a lossy image format.
path: 'page.jpg' Writes screenshot bytes to a file. Puppeteer can infer format from the extension, but an explicit type makes the choice clear. Use a .jpg or .jpeg extension for readable output naming.
quality JPEG quality from 0 to 100; it does not apply to PNG. Set it when you need to trade image fidelity against encoded output size. Inspect results rather than assuming one value fits every page.
fullPage: true Captures the full document instead of only the current viewport. The default is false. Use for long articles or pages that must be captured from top to bottom.
clip Defines a rectangular region to capture. Use for a fixed area such as a chart or card. Coordinates and dimensions should match the rendered page.
captureBeyondViewport Controls capture beyond the viewport. The documented default is false without a clip and true when a clip is supplied. Set deliberately if combining a clip with off-viewport coordinates.

Puppeteer supports png, jpeg, and webp screenshot formats. JPEG quality does not affect PNG. The documentation does not prescribe a universally best quality or publish comparative size and quality measurements, so choose by inspecting representative outputs. See the ImageFormat reference.

3. Capture a viewport, full page, or clipped region

For a viewport screenshot, omit fullPage or set it to false. The page’s current viewport dimensions determine the capture size. To capture the whole document, set fullPage: true. To capture a region, provide clip with coordinates and dimensions:

await page.screenshot({
  path: 'region.jpg',
  type: 'jpeg',
  quality: 85,
  clip: { x: 20, y: 30, width: 640, height: 360 },
});

Use the Page.screenshot() API reference for the current option types and defaults. If the coordinates or dimensions are invalid for the rendered page, adjust the clip to a valid region.

4. Capture one element

When you need a single DOM element rather than a viewport or document, select it and call its screenshot method. Puppeteer scrolls the element into view if it is hidden. A detached element causes an error, so find the element after navigation and avoid retaining a handle across a page update that may replace it.

const card = await page.waitForSelector('.product-card');
if (!card) throw new Error('Product card was not found');
await card.screenshot({
  path: 'product-card.jpg',
  type: 'jpeg',
  quality: 90,
});

Element screenshots are covered in the official screenshots guide.

5. Return JPEG data instead of saving a file

If you omit path, page.screenshot() returns image data. Its default result is a Uint8Array; the API can also return base64 data when base64 encoding is requested. This is useful when the next step uploads the image or stores it in an object store rather than writing a local file.

const bytes = await page.screenshot({ type: 'jpeg', quality: 85 });
// bytes is a Uint8Array by default; pass it to your storage or response code.

6. Make page readiness explicit

waitUntil: 'networkidle2' is the condition used in Puppeteer’s guide example, but it is not proof that the exact content you need is ready. A page may continue making requests, or render its main content after a quiet period. For dynamic pages, wait for a meaningful selector or application state before capture:

await page.goto('https://example.com/report', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-report-ready="true"]');
await page.screenshot({ path: 'report.jpg', type: 'jpeg', quality: 85, fullPage: true });

Choose the wait strategy based on the site. A fixed delay can help with a known animation or delayed widget, but it adds time and may still be too short or unnecessarily long. A selector tied to the content is usually a clearer readiness signal when the page exposes one.

7. Common errors and fixes

Symptom Likely cause What to do
Browser fails to launch Browser binary or required system libraries are missing, or the runtime cannot start the bundled browser. Install the browser and runtime dependencies for the environment, or configure Puppeteer to use an available compatible executable.
Screenshot is blank or missing page content Capture ran before the application rendered, navigation did not reach the expected page, or content requires additional client-side work. Check the navigation result and URL, then wait for a page-specific selector or application-ready state before capture.
Navigation hangs or times out The page keeps network connections open, is slow, or the selected wait condition never occurs. Use a readiness condition suitable for the site, handle navigation errors, and set a timeout appropriate to your job. Do not treat network idle as a universal completion signal.
Element screenshot reports a detached node The page replaced or removed the element after the handle was obtained. Wait for the element after the relevant render/update and obtain a fresh handle immediately before capture.
JPEG settings appear to have no effect The output is PNG, where quality does not apply, or the output type was inferred differently than intended. Set type: 'jpeg', use a JPEG filename, and inspect the actual output format.
Clip is empty or the wrong region Clip coordinates or dimensions do not correspond to the current layout or viewport. Recalculate the region after the page has rendered and confirm its x/y position and width/height.
Full-page image omits expected late content Lazy-loaded or dynamic content had not appeared when capture started. Wait for the content or trigger the page behavior that loads it before taking the full-page screenshot.

8. Performance, reliability, and cost

Screenshot work includes browser startup, navigation, page rendering, image encoding, and output storage. For repeated captures, avoid launching more browser processes than your machine can support; manage browser and page lifetimes carefully and close them in cleanup paths. Full-page captures and high-resolution pages can produce larger images and take longer to encode than smaller viewport captures. JPEG quality is an output choice to evaluate against the visual needs and storage or transfer constraints of your workload; Puppeteer’s references do not provide a universal size reduction or speed benchmark.

For reliability, handle navigation and capture failures, use page-specific readiness checks where possible, and ensure the browser closes in a finally block. The code above is a local browser workflow; its cost depends on the compute and storage environment where you run it. For browser provisioning, capture operations, and result handling without setting up Puppeteer, ScreenshotNeo offers a screenshot API and MCP server for developers.

Or skip the browser setup

One GET request to ScreenshotNeo can return a screenshot as PNG, JPEG, or WebP, or a PDF. For a JPEG, use the API’s documented options in the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

For an explicitly named JPEG output, request the JPEG format using the API’s format option as documented, and use a .jpg filename. The one-call example above saves the returned image to a file; see the docs for parameter names and supported output configuration.

ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers say the page verdict and whether the request was billed. Its MCP server gives AI agents tools to take screenshots, inspect page information, and capture PDFs. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

FAQ

Can Puppeteer save a screenshot directly as a JPEG?

Yes. Set type: 'jpeg' in the screenshot options and provide a JPEG path such as page.jpg.

What is the valid JPEG quality range?

Puppeteer documents values from 0 to 100. The reference does not specify one best value for every page.

Does JPEG quality change PNG output?

No. The quality option applies to JPEG, not PNG.

Can I capture a single DOM element?

Yes. Get an element handle and call its screenshot() method. Puppeteer scrolls it into view when needed; a detached handle will error.

Can I get bytes without writing a file?

Yes. Omit path and use the returned Uint8Array, or request base64 output using the API’s supported encoding option.