How to Set Screenshot Quality for JPEG Captures in Puppeteer
Set Puppeteer’s JPEG screenshot quality with the `quality` option, choose a value from 0 to 100, and check the resulting image for your use case.
Set type: 'jpeg' and a numeric quality from 0 to 100 in page.screenshot(). For example, quality: 80 requests a JPEG capture at that setting:
await page.screenshot({
type: 'jpeg',
quality: 80,
path: 'capture.jpg',
});
Puppeteer documents the range, but does not prescribe a best value or guarantee a particular file size or visual result for a given number. Compare representative captures from the browser and runtime you deploy. The official references are the ScreenshotOptions API, Page.screenshot() API, and screenshots guide.
Runnable example
This Node.js example launches Chromium, captures a page as JPEG, and closes the browser even if capture fails. Install Puppeteer in your project with npm install puppeteer, then save this as capture.mjs and run node capture.mjs.
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1280, height: 800 },
});
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.screenshot({
type: 'jpeg',
quality: 80,
path: 'capture.jpg',
fullPage: true,
});
} finally {
await browser.close();
}
For the smallest focused example, after you already have a loaded page:
const image = await page.screenshot({ type: 'jpeg', quality: 80 });
Without path, Puppeteer returns image bytes as a Uint8Array. Supplying path saves the capture to that location. With encoding: 'base64', the result is a base64 string instead of image bytes. See the method reference for the return type and options.
What the quality value means
quality is an optional number from 0 through 100 for JPEG screenshot encoding. It is a setting, not a promise of a particular number of bytes or a universal visual quality. The documentation does not provide a conversion from quality numbers to file size, nor a recommended default for every workload.
- Use a lower value when smaller output matters more and the image remains acceptable for its purpose.
- Use a higher value when visual detail matters more and the resulting size is acceptable.
- Inspect the actual output at the display size and zoom level your users need.
- Compare the same pages, viewport, device scale factor, and browser build when evaluating alternatives.
Do not infer that quality 80 means an 80% file-size reduction or that two different browser builds will produce identical bytes. Puppeteer documents the valid range, not those outcomes.
Options that affect the capture
| Option | Effect and guidance |
|---|---|
type |
Set to 'jpeg' to make the format explicit. Supported screenshot types include JPEG, PNG, and WebP; if omitted, Puppeteer infers the type from the path extension. |
quality |
Optional numeric JPEG quality from 0 to 100. It does not apply to PNG. |
path |
Writes the image to a file. Use a matching .jpg or .jpeg extension to keep the filename clear. |
encoding |
Use 'base64' when a base64 string is needed; otherwise the method returns image bytes. |
fullPage |
Captures the full page rather than only the current viewport. Larger captures can take more time and produce more data. |
clip |
Captures a specified rectangular region. Do not combine it with fullPage. |
omitBackground |
Can omit the default background for supported formats; JPEG has no transparency, so use PNG when transparent output is required. |
Check the installed Puppeteer version’s API reference when using less common combinations or relying on specific option behavior. The current reference describes quality as not applicable to PNG.
JPEG versus PNG and WebP
JPEG is useful when you need a broadly consumable photographic image and want to tune its encoding quality. It does not preserve transparency. PNG is lossless and appropriate when exact edges, text, or transparency matter, but Puppeteer’s JPEG quality option does not apply to PNG. WebP is another supported screenshot type; check the target consumers and your installed Puppeteer documentation before choosing it.
// JPEG: quality applies
await page.screenshot({ type: 'jpeg', quality: 75, path: 'page.jpg' });
// PNG: omit quality
await page.screenshot({ type: 'png', path: 'page.png' });
// WebP: choose only if your consumers support it
await page.screenshot({ type: 'webp', path: 'page.webp' });
For formats other than JPEG, do not pass quality expecting Puppeteer to apply the same behavior. Select the output format based on transparency, fidelity, compatibility, and the results you observe in your own pipeline.
Choosing and validating a value
- Pick representative pages, including text-heavy layouts, photographs, gradients, and any content that matters to your users.
- Keep viewport, device scale factor, page state, and browser version fixed.
- Capture JPEGs at a few candidate values within 0–100.
- Compare readability and visual artifacts at the actual rendered size, and compare file sizes from those captures.
- Choose the lowest setting that meets your visual requirement, then repeat after material browser or page changes.
This is a project-specific selection process, not a Puppeteer benchmark or universal recommendation. The official documentation supplies the permitted range but does not quantify the trade-off.
Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The output is PNG even though you expected JPEG. | The type was inferred from a path with a PNG extension, or an explicit type was not set. | Set type: 'jpeg' and use a .jpg or .jpeg path. |
Changing quality has no effect on the PNG output. |
The quality option does not apply to PNG. | Use type: 'jpeg' when you need JPEG quality control, or keep PNG and omit the option. |
| Puppeteer rejects the quality value. | The value is outside the documented 0–100 range, is not numeric, or the installed version handles validation differently. | Pass a number in range and check the reference for your installed version. The changelog notes a quality-validation correction in Puppeteer 22.13.0. |
| The file is larger or looks different than expected. | The number does not guarantee a fixed size or appearance; content and runtime affect the result. | Compare representative captures from the deployed browser setup and adjust based on measured output. |
| The saved image has the wrong filename extension. | The path extension does not match the intended format. | Set the type explicitly and make the path extension match. |
| The captured page is incomplete or blank. | The page may not have reached the state your capture requires; a navigation wait condition alone may not cover delayed application rendering. | Wait for a relevant selector or application-ready condition before calling screenshot(); use a bounded timeout appropriate to the page. |
Performance, reliability, and cost
JPEG quality controls image encoding; it does not reduce the work required to navigate to or render the page. Full-page screenshots and large viewports can involve more pixels and produce larger output. If capture throughput matters, measure navigation, rendering, and encoding in your own deployment rather than treating the quality number as a performance guarantee.
For reliable captures, use a known page-ready condition, set appropriate navigation and job timeouts, close pages and browsers in cleanup paths, and record the Puppeteer version and browser build alongside output changes. The Puppeteer changelog records that version 22.13.0, released July 11, 2024, corrected validation of the screenshot quality parameter; older installations should check their own release documentation.
Self-hosted Puppeteer has no per-screenshot ScreenshotNeo fee, but your infrastructure, browser runtime, storage, and engineering time have costs. Estimate them from your deployment. If you want to avoid maintaining browser capture infrastructure, ScreenshotNeo offers a website screenshot API and MCP server; its plan prices and capture behavior are described below.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. Make one GET request with a URL to receive an image or PDF. See the API documentation for the 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)
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 and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Response headers indicate the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for AI agents and MCP clients. - The free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan.
Sign up for 1,000 free screenshots a month, with no card.
FAQ
Does a higher quality number always mean a better screenshot?
It requests a higher JPEG quality setting, but inspect the actual output in your browser version and capture workflow; Puppeteer does not document a universal visual guarantee.
Can I use decimal values?
The API reference specifies a number in the 0–100 range but does not establish that every fractional value behaves identically across versions. Prefer an integer unless your installed version’s behavior has been confirmed.
What changed in Puppeteer 22.13.0?
The changelog says that release corrected validation of the quality parameter. It does not recommend a particular value.
Can I convert a returned Uint8Array to a file?
Yes. Node.js can write the returned bytes with writeFile from node:fs/promises; alternatively, pass path directly to page.screenshot().


