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

Use a data URL as the image source in the HTML you send to your PDF renderer. Encode the original image bytes (not a filename or an existing data URL), prepend the matching MIME type, and place the result after data::

<img alt="Company logo" src="data:image/png;base64,ENCODED_IMAGE_BYTES">

This removes a separate file or network lookup for that image, but the renderer must support data URLs and the image format. The sections below show a complete workflow, engine-specific details, failure diagnosis, and production considerations.

What a Base64 image in HTML actually is

Base64 is text representing binary image bytes. HTML does not display the text by itself. It displays the image when the text is wrapped in a correctly formed data URL:

data:[media-type][;base64],ENCODED_BYTES

For example, a PNG uses data:image/png;base64,; a JPEG uses data:image/jpeg;base64,; and an SVG can use an appropriate SVG media type. The label must describe the bytes that follow it. A PNG payload labeled as JPEG can fail to decode or render unpredictably.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Encode bytes, never a path

Read the binary file and Base64-encode those bytes. Encoding /images/logo.png, a URL, or an already complete data URL produces invalid image data.

Keep the payload intact

Put the complete string after the comma in src. Do not add spaces or line breaks unless your renderer explicitly documents that it accepts them. HTML escaping still applies when you insert the value into an attribute.

End-to-end workflow

  1. Read the source image as bytes. Preserve the original binary content.
  2. Identify its actual format. Use the corresponding MIME type, such as image/png or image/jpeg.
  3. Build the data URL. Concatenate the prefix, a comma, and the Base64 text.
  4. Insert it into HTML. Use a normal <img> element with useful alternative text.
  5. Send the HTML to your PDF engine. Configure a base URL separately for any other relative resources.
  6. Open the resulting PDF. Check that the image appears, has the intended dimensions, and did not make the file unexpectedly large.

Python with WeasyPrint

WeasyPrint’s supported-features documentation explicitly lists data URIs. Its <img>, <embed>, and <object> elements accept raster formats supported by Pillow and SVG. SVG images are rendered as vectors in PDF output.

from base64 import b64encode
from pathlib import Path
from weasyprint import HTML

image_path = Path("logo.png")
image_bytes = image_path.read_bytes()
encoded = b64encode(image_bytes).decode("ascii")
html = f"""
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <style>
      @page {{ size: A4; margin: 18mm; }}
      img.logo {{ width: 160px; height: auto; }}
    </style>
  </head>
  <body>
    <img class="logo" alt="Company logo"
         src="data:image/png;base64,{encoded}">
    <h1>Invoice</h1>
  </body>
</html>
"""

HTML(string=html, base_url=str(Path.cwd())).write_pdf("invoice.pdf")

base_url is not needed for the embedded image, because the data URL is self-contained. It is important when the same document contains relative CSS, fonts, or other files. WeasyPrint documents that relative URLs can be invalid for HTML(string=...) when no base_url is supplied.

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

Controlling image size in WeasyPrint

WeasyPrint’s API and command-line options include image optimization and a maximum resolution for images embedded in the PDF. Option names can vary by installed version, so check the documentation for your deployed release before adding them to a build script. These settings can reduce output size, but downsampling can also reduce print quality.

Node.js with Puppeteer

Puppeteer accepts the same data URL because Chromium resolves it as an inline image. This example reads a PNG, creates the HTML, waits for the image to be complete, and writes a PDF.

import { readFile } from "node:fs/promises";
import puppeteer from "puppeteer";

const bytes = await readFile("logo.png");
const encoded = bytes.toString("base64");
const html = `<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    @page { size: A4; margin: 18mm; }
    img { width: 160px; height: auto; }
    /* Use this only when exact screen colors are required in print. */
    * { -webkit-print-color-adjust: exact; }
  </style>
</head>
<body>
  <img id="logo" alt="Company logo"
       src="data:image/png;base64,${encoded}">
  <h1>Invoice</h1>
</body>
</html>`;

const browser = await puppeteer.launch();
try {
  const page = await browser.newPage();
  await page.setContent(html, { waitUntil: "load" });
  await page.waitForFunction(() => document.querySelector("#logo")?.complete);
  await page.pdf({ path: "invoice.pdf", format: "A4", printBackground: true });
} finally {
  await browser.close();
}

Page.pdf() uses the print CSS media type by default. A page that looks correct in a screen preview can therefore change in the PDF if your stylesheet has @media print rules or print-specific defaults. Chromium also modifies page colors for printing unless you use the documented -webkit-print-color-adjust behavior where exact colors are required.

wkhtmltopdf considerations

wkhtmltopdf’s usage documentation lists image loading as enabled by default and provides --no-images to disable it. If an inline image is missing, first confirm that your command does not include that switch. Its print-media selection and separate page-load and media-load error handling are also relevant when diagnosing failures.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
wkhtmltopdf --print-media-type input.html output.pdf

Do not infer from that option alone that every image format or every data URL is supported. Verify the exact wkhtmltopdf build and inspect reported media errors.

Data URLs versus relative and remote images

Source form Resource lookup Typical failure
data:image/...;base64,... Contained in the HTML; no separate fetch Truncated payload, wrong MIME type, or unsupported renderer format
images/logo.png Resolved relative to a base URL or document location No base URL when HTML is supplied as a string
https://example.com/logo.png Requires network access, DNS, TLS, and permission Network failure, authentication, or blocked outbound requests

Embedding one image does not make the entire document self-contained. Fonts, stylesheets, background images, and other resources still follow their own resolution rules.

Quality, size, and security decisions

Choose the source format deliberately

  • Use PNG for lossless diagrams, logos, and transparency.
  • Use JPEG for photographic content where its lossy compression is acceptable.
  • Use SVG for scalable line art when your renderer supports it.

Base64 increases the textual representation compared with the original binary. The exact PDF-size effect depends on the renderer’s decoding, compression, image resolution, and whether it recompresses the image. No universal Base64 or PDF size ceiling is established; measure representative documents with your installed engine.

Control untrusted content

Inlining avoids a network fetch for that image, but it does not make arbitrary HTML safe. Sanitize untrusted markup, restrict scripts according to your renderer, and control access to local files and outbound URLs. A renderer may process other resources in the same document even when the main image is embedded.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting missing images

The PDF contains a blank area

  • Confirm the Base64 text came from the image bytes and was not cut off.
  • Check that the MIME type matches the actual file format.
  • Inspect the generated HTML for accidental whitespace, quoting errors, or an omitted comma after the data-URL prefix.
  • Verify the renderer and its installed version document support for data: URLs and that image format.

The embedded image works, but other images do not

This usually indicates resource-resolution rather than Base64 failure. Supply a correct base_url to WeasyPrint for string input, or replace other relative paths with valid absolute paths or URLs permitted by your deployment.

The browser preview differs from the PDF

Inspect print CSS. Puppeteer generates PDFs with the print media type, and wkhtmltopdf can be instructed to use print media. Check dimensions, @media print rules, backgrounds, and color-adjust settings.

wkhtmltopdf shows media errors

Ensure image loading has not been disabled with --no-images. Separate page-load and media-load diagnostics to determine whether the failure concerns the document itself or an image/resource.

The PDF is unexpectedly large or slow

Measure the input image and resulting PDF rather than relying on a presumed limit. Resize oversized source images to their intended physical dimensions, use an appropriate format, and apply the renderer’s documented image optimization or maximum-resolution controls where available. Keep the original for archival workflows if quality requirements differ.

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

Testing and production checklist

  • Test at least one PNG, JPEG, and (if needed) SVG representative of production content.
  • Test transparent backgrounds, large images, and long documents.
  • Run the same tests against the exact renderer version deployed in production.
  • Verify page breaks, print styles, image scaling, and accessibility text.
  • Record output size and rendering time for realistic workloads.
  • Set explicit timeouts and capture renderer logs, including media errors.
  • Keep a fallback path for a missing or corrupt source image if the document is business-critical.

Or skip the browser setup

If your input is a public webpage rather than hand-built HTML, ScreenshotNeo can return a PNG, JPEG, WebP, or PDF from one GET request. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status.

For a PDF capture:

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 documentation for PDF options, paper size, margins, landscape mode, page ranges, and the other capture controls. Python and Node.js equivalents are:

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}`);

It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Can I Base64-encode an image URL instead of downloading it?

Not directly. Fetch the image bytes first, then encode those bytes. Encoding the URL characters creates text that is not an image.

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

Should I embed every document asset as Base64?

Only when the self-contained resource is worth the larger HTML and possible PDF payload. For large collections, controlled local or remote resources with an explicit base URL may be easier to manage.

Does Base64 guarantee that an image will appear in every PDF engine?

No. Support depends on the renderer version, accepted formats, security settings, and print behavior. Validate your chosen engine with representative files.

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.