01 · Diagnose the problem

PNG or JPEG when your application generates the image

Generated artifacts are not photographs and they are not screenshots of photographs. A social card, an invoice or a badge is mostly flat colour and text, which is the exact content JPEG compresses worst and PNG compresses best - and the moment a photograph or a wide gradient enters the same card, that reverses.

4 min readPublished Updated
What you actually see

Text picks up a halo of grey speckle at the edges of glyphs, or a 1200x630 card leaves the renderer as a multi-megabyte PNG that a CDN then serves on every page view.

Reproduce it

  1. 01Render the same markup as PNG and as JPEG at quality 80, and compare the two file sizes rather than the two previews.
  2. 02Zoom to 400% on a hard edge - the boundary between text and background - and look for ringing that is absent from the PNG.
  3. 03Multiply the pixel density by two and measure again: the PNG grows roughly fourfold, and whichever format was cheaper at 1x may not be at 2x.
02 / Do it yourself

Encode the same artifact twice and weigh both

Do not choose from a rule of thumb. Encode the artifact you actually ship in both formats, print the byte sizes, and keep the smaller one that survives inspection at the size it will be displayed.

compare-formats.mts
const page = await browser.newPage({ viewport: { width: 1200, height: 100 } });
await page.setContent(card, { waitUntil: "load" });
await page.evaluate(() => document.fonts.ready);

const png = await page.screenshot({ type: "png", fullPage: true });
const jpeg = await page.screenshot({ type: "jpeg", quality: 80, fullPage: true });

console.log("png  ", (png.length / 1024).toFixed(1), "KiB");
console.log("jpeg ", (jpeg.length / 1024).toFixed(1), "KiB");

// Flat colour and text: the PNG is usually smaller AND lossless.
// A photograph or a wide gradient: the JPEG is usually several times smaller.
03 / Where it breaks

When the format is not what is wrong

The call above is small. Everything around it is the system — and the system is what you would be signing up to own.

The artifact needs transparency

JPEG has no alpha channel. A card meant to sit on an unknown background has to be PNG, or the transparent area is flattened - usually to black or white, decided by the encoder rather than by you.

The content is photographic

A hero image or a wide smooth gradient makes PNG expensive: lossless compression cannot exploit the redundancy JPEG was designed for. Here the same perceived quality can cost several times fewer bytes as JPEG.

Pixel density multiplies the decision

Doubling device scale roughly quadruples the pixel count. A PNG that was acceptable at 1x can stop being acceptable at 2x while the JPEG at the same density stays reasonable.

The encoder is not the bottleneck

If the artifact is large because the layout is 6000 pixels tall, no format choice fixes it. Bound the height or capture the element instead of the document.

Keep the DIY version when

  • The artifact is displayed once, at one size, and nobody pays for the bytes - an internal report or a one-off export.
  • The content is flat colour and text with no transparency, where PNG is simultaneously smaller and lossless and there is no trade left to make.
04 / The recipe

Choose PNG or JPEG for a generated image

Send the markup and ask for the format the measurement chose. The capture grows to the height of the content, so the comparison is between two encodings of the same pixels rather than two different crops.

Capture settings
Enter the source, choose your options, then run the capture.
Result
Your capture will appear here and stay in view.
waiting

No result yet

Complete the settings and run the tool. Images, PDFs, text, and video all preview in this panel.

Send this exact request
cURL, TypeScript and Python are generated from the same configuration as the demo.
curl --fail-with-body "https://api.pagecapture.dev/v1/take" \
  -H "X-Access-Key: $PAGECAPTURE_KEY" \
  -H "Content-Type: application/json" \
  --data '{"html":"<article style=\"width:1200px;padding:80px;font:600 56px/1.18 system-ui,sans-serif;color:#101010;background:#f2f0eb\">Invoice 1042 settled<p style=\"margin:24px 0 0;font-size:22px;font-weight:500;opacity:.6\">Flat colour and text - the case PNG wins</p></article>","format":"png","full_page":true,"viewport_height":100}' \
  -o capture.png
05 / Output, limits, cost, failures

What a format-aware render gives back

Output

One file in the format you asked for, at the width you set and as tall as the markup, encoded by the same Chromium build every time.

Cost

One successful, non-cached capture costs one credit. Failures, including platform failures, cost zero; cache hits cost zero.

1 creditper successful non-cached capture

Limits

  • Transparency survives only in a format with an alpha channel; asking for it in JPEG silently flattens it.
  • Quality applies to lossy formats only - it is ignored by PNG, which has nothing to discard.
  • A very tall document is bounded by the capture limits, not by the encoder: the format is not what makes it fit.

Common errors

A tall document at a high pixel density produces an artifact past the size limit - the usual cause is density, not format.

HTTP 400 · terminal

The inline markup carries large embedded data URLs and the request body passes the limit.

HTTP 413 · terminal

06 / Take it for a run

Try it against your own page

Swap the example for a page you care about. The runner keeps every option from this guide, and carries the whole configuration into the playground — no retyping, no starting over.

Return to the configured runner
07 / Verification
Tested and reviewed

Written by PageCapture Engineering. Reviewed by PageCapture render maintainers. Verified 2026-08-26 by running the published code against a fixture.

The recipe was normalized through the public contract and its markup rendered with the pinned Chromium build; the CI fixture run has not executed this piece yet.

engine-crunknown-pwunknown-f2026-07-1-b2026-08-1StatusImage encoding referenceEditorial method

Sources and verification basis

Sources support the browser and API behaviors named above. PageCapture-specific limits and billing are taken from the public contract; external sources are used for the underlying browser behavior.

  1. Defines the alpha channel and the lossless compression this guide relies on.

  2. Page.screenshotPlaywright

    Documents the type and quality options used by the DIY comparison.