October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
Base64

How to Fix Broken Base64 Images in Puppeteer PDF Headers

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a Base64 image disappears from a Puppeteer PDF header, first prove that the final headerTemplate contains a valid, correctly prefixed data URI. Then reduce the PDF call to one image, record both the Puppeteer package and the Chrome executable versions, and compare browsers. A 2025 Puppeteer report saw a JPEG header work in 24.3.0 and fail from 24.4.0 onward, while a maintainer reproduced the failure in stable Chrome and said it seemed fixed in Canary. No stable Chrome release is identified as containing that fix, so do not assume that upgrading to a particular version will solve every case.

What is actually failing?

Puppeteer prints a header only when displayHeaderFooter is enabled. In the documented PDFOptions interface (page marked version 25.12.0 when accessed), headerTemplate is an HTML string, and the built-in placeholder classes include date, title, url, pageNumber and totalPages. The default for displayHeaderFooter is false.

A header template is a separate, restricted print fragment. Treat it as self-contained HTML: use a literal src, inline styles and enough top margin. Do not assume that page CSS, page JavaScript or the page’s resource context is inherited. A historical issue records a script in a header/footer template not running in its reproduction (issue #2167), and another records a relative image path rendering as a gray outline (issue #2443). Those reports are warnings about isolation, not proof that every relative URL fails or that Base64 always succeeds.

Start by inspecting the generated header

Log the exact final string

Inspect the string after all templating has run, not the source variable that was supposed to become an image. Redact secrets before writing it to a log. Look for an unreplaced token such as {{logo}}, a missing value, a second prefix, a quote inserted into the payload, or a line break in the encoded data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
console.log(headerTemplate.replace(/base64,[^"']+/i, 'base64,[redacted]'));

Check the data-URI contract

  • PNG data must begin with data:image/png;base64,.
  • JPEG data must begin with data:image/jpeg;base64, (or the MIME type your encoder actually produced).
  • Put the MIME prefix exactly once. If pngBase64 already contains a complete data URI, do not prepend another one.
  • Keep the payload variable to encoded bytes when the template supplies the prefix.
  • Do not insert whitespace, a newline, or an unintended quote into the Base64 payload.

These checks identify malformed output; the issue reports do not establish that one particular formatting mistake is the cause in every failure.

Validate the image outside Puppeteer

A Base64-shaped string can still decode to invalid bytes. Decode the payload independently and open the resulting file. This also catches a variable that contains an HTML error page, a truncated read, or a URI prefix that was accidentally included in the bytes.

import fs from 'node:fs';

const dataUri = `data:image/png;base64,${pngBase64}`;
const match = dataUri.match(/^data:([^;]+);base64,(.+)$/s);
if (!match) throw new Error('Not a single, complete Base64 data URI');
fs.writeFileSync('debug-header.png', Buffer.from(match[2], 'base64'));

Open debug-header.png with an image viewer. If it cannot be opened, fix the source bytes before investigating PDF rendering.

Build a minimal PDF reproduction

Remove your application layout, framework CSS and dynamic header generation. Keep one page, one image and the actual data URI. Set a top margin large enough that the header is inside the printable area.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
import puppeteer from 'puppeteer';

const pngBase64 = '...'; // valid PNG bytes, Base64 encoded; no data URI prefix
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent('<main>Minimal PDF reproduction</main>', {
  waitUntil: 'load'
});

const pdf = await page.pdf({
  displayHeaderFooter: true,
  headerTemplate: `
    <div style="width:100%; margin:0; padding:0;">
      <img
        src="data:image/png;base64,${pngBase64}"
        style="display:block; width:110px; height:auto;"
        alt="Company logo"
      />
    </div>
  `,
  footerTemplate: '<span class="pageNumber"></span> / <span class="totalPages"></span>',
  margin: { top: '1in', bottom: '0.5in' }
});
await browser.close();

This is a diagnostic pattern, not a guaranteed workaround for the reported regression. Change the MIME type, dimensions and margins to match your asset and document. If this exact image still fails, the small reproduction gives you something that can be compared across browser versions.

Record both versions, not just “Puppeteer”

Puppeteer’s npm version and the Chrome/Chromium executable it launches are different variables. Record both in the failing environment and the working one.

npm list puppeteer
node --version
const browser = await puppeteer.launch();
console.log('browser:', await browser.version());
console.log('executable:', browser.process()?.spawnargs?.[0]);

The report in Puppeteer issue #13726 describes Node 22.14.0, npm 10.9.2 and Windows; its author said the Base64 JPEG worked with Puppeteer 24.3.0 and failed beginning with 24.4.0. That is an individual 2025 report, not a universal compatibility rule.

Compare a controlled browser change

Once the minimal case is valid, run it against another executable while keeping the template, image bytes, options, operating system and runtime unchanged. In the same issue discussion, Puppeteer collaborator OrKoN wrote on 2025-04-04 that they could reproduce “Printing failed” with current stable Chrome and that it “seems to be fixed with canary” (comment). The comment does not name the Canary build or a stable release containing the correction.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use Canary as an investigative comparison, not as a confirmed production fix. Before changing production, verify the exact executable and rerun the minimal PDF in your deployment environment. The available reports do not establish whether the behavior persists in every current browser build.

Keep header markup self-contained

  • Use inline CSS for display, width and height.
  • Use a literal image src in the final template.
  • Reserve vertical space with margin.top; otherwise a valid header can be clipped.
  • Do not depend on a page stylesheet, a script in the template, or a page-side transformation to create the image.
  • Keep the header simple while diagnosing. Add other markup only after the image works.

The API documents the template as HTML and documents placeholder classes, but it does not promise that the template executes JavaScript or inherits the main document’s resource context (Puppeteer PDFOptions).

Use a comparison record to isolate the variable

Variable What to record Why it matters
Puppeteer Exact package version, such as 24.3.0 or 24.4.0 The 2025 report places its change in this comparison.
Browser Actual Chrome/Chromium executable and version Puppeteer can launch a browser different from the one you expected; the maintainer reproduced a stable-versus-Canary difference.
Image PNG or JPEG, decoded bytes, MIME prefix Confirms that the same valid asset is used in every run.
Template Exact final HTML after substitution Separates templating errors from print rendering.
Runtime Node version, operating system and launch arguments The issue report identifies Windows and Node 22.14.0; do not generalize that result to Linux or macOS.
PDF options displayHeaderFooter, margins and both templates A missing flag or insufficient margin can look like a missing image.

Troubleshooting by symptom

The header is completely absent

Confirm displayHeaderFooter: true and a nonzero top margin. Check that the PDF call actually receives the template you logged; a conditional branch may be passing an empty string.

Text appears, but the image is missing

Decode the payload, verify one MIME prefix, and compare the final src with the standalone file. Then run the minimal reproduction. If the minimal image fails only with one browser executable, treat it as a version/environment investigation rather than a CSS problem.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A gray outline or broken-image icon appears

Inspect for a relative path such as /public/images/logo.png. A 2018 report recorded that kind of result, but it does not prove that all relative paths fail. Replace it temporarily with a validated literal data URI and compare.

The image is clipped or overlaps the page

Increase margin.top, reduce the image height, and keep the wrapper’s margin and padding explicit. Header space is outside the page body; a valid image can be present but outside the printable region.

It works locally but fails in deployment

Print the executable path and browser version in both environments, save the final template, compare decoded image hashes, and compare Node, operating system and PDF options. Do not compare only the Puppeteer package number.

Changing to a newer stable release did not help

There is no documented stable release in the cited discussion that guarantees a fix. Re-run the minimal case, test a controlled alternate executable, and preserve the failing combination for an issue report. Avoid claiming that Canary or any current stable build is universally corrected.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
The SQL Programming Language: .
  • Used Book in Good Condition
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance and reliability considerations

Inlining a small logo avoids a separate resource lookup in the header, but it does not remove the need to validate bytes or leave print space. Keep the diagnostic asset small, create one minimal page, and avoid unrelated network requests while comparing browsers. For production, pin and record the browser executable used by your deployment, retain a representative PDF fixture, and rerun that fixture when upgrading Puppeteer or Chrome. A passing result on one operating system is not evidence for every other platform.

Or skip the browser setup

If you need a clean image of a URL rather than a custom Puppeteer PDF header, ScreenshotNeo provides a website screenshot API and MCP server. It accepts one GET request and returns PNG, JPEG, WebP or PDF. Before capture it accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.

For a direct request, see the ScreenshotNeo API documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free, and every feature is included on every plan. If that fits your workflow, sign up free.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What to report when opening an issue

  • The smallest HTML body and the exact final header template, with the Base64 payload redacted if necessary.
  • The image format, MIME prefix and a separately validated sample asset.
  • Puppeteer package version, Node version, operating system, executable path and browser version.
  • The complete page.pdf() options, including margins and whether a footer is present.
  • Which combinations pass or fail, especially the 24.3.0/24.4.0 comparison if it reproduces.

This information lets maintainers distinguish malformed data, template isolation, margin problems and an upstream browser regression without guessing.

Frequently Asked Questions

Do Puppeteer header placeholders work inside an image’s Base64 string?

No. Placeholders such as pageNumber and totalPages are documented HTML classes for print fields; keep the image data URI literal and separate from those elements.

Should I deploy Chrome Canary to fix this?

Not as a blanket recommendation. Canary was reported as apparently fixed in a dated April 2025 reproduction, but no build or corresponding stable release was identified. Validate your exact minimal case first.

Can I use a relative logo URL instead of Base64?

You can test it, but a historical report showed a relative path producing a gray outline. For isolation, use a validated literal data URI and compare the results.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.