ScreenshotNeo

BlogHTML to image & PDF

How to Add an Image to Multiple PDF Pages With jsPDF

Repeat addImage on each jsPDF page to place the same image throughout a PDF. Learn how to size, center, reuse, and troubleshoot it.

By the ScreenshotNeo team30 September 20269 min read

How to Add an Image to Multiple PDF Pages With jsPDF

To add the same image to multiple pages in jsPDF, call addImage() once for the first page, then call addPage() and addImage() for each remaining page. A new jsPDF document already has its first page. Drawing only affects the currently active page, so calling addImage() repeatedly without adding or selecting pages puts the image repeatedly on one page.

import { jsPDF } from 'jspdf';

const doc = new jsPDF({ unit: 'mm', format: 'a4', orientation: 'portrait' });
const imageData = 'data:image/png;base64,...';
const x = 10;
const y = 20;
const width = 190;
const height = 100;
const pageCount = 3;

// The first page already exists.
doc.addImage(imageData, 'PNG', x, y, width, height);

// Add the image to each additional page.
for (let page = 1; page < pageCount; page += 1) {
  doc.addPage();
  doc.addImage(imageData, 'PNG', x, y, width, height);
}

doc.save('output.pdf');

The example uses millimeters because that is the document’s unit. Choose coordinates and dimensions in that same unit. For the API’s image input types and parameters, see the jsPDF addImage documentation; for page creation, see the jsPDF documentation.

1. Install jsPDF and create a document

For a JavaScript project using npm, install jsPDF and import its constructor:

npm install jspdf
import { jsPDF } from 'jspdf';

const doc = new jsPDF({
  orientation: 'portrait',
  unit: 'mm',
  format: 'a4'
});

You can also use jsPDF in a browser build that exposes the library through your bundler. Keep document creation and image drawing in the same client-side flow if the image is a browser object such as an HTMLCanvasElement. A Node.js script can use data that jsPDF accepts, such as a data URL or byte array, subject to the runtime and build setup. The browser-only objects HTMLImageElement and HTMLCanvasElement are not available in ordinary Node.js code.

2. Load an image into a format jsPDF accepts

addImage() accepts a data URL string, HTMLImageElement, HTMLCanvasElement, Uint8Array, or RGBA data. A data URL is convenient for a self-contained example. In a browser, you can turn a loaded image into a data URL like this:

The first page is already present; add the image there, then add a page and image for each repeat.
The first page is already present; add the image there, then add a page and image for each repeat.
async function imageUrlToDataUrl(url) {
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`Image request failed: ${response.status}`);
  }
  const blob = await response.blob();

  return await new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = () => reject(reader.error);
    reader.readAsDataURL(blob);
  });
}

Use an image URL your application is permitted to fetch. Cross-origin restrictions can prevent a browser from reading remote image bytes, especially when drawing a remote image to a canvas. If you control the server, configure the appropriate cross-origin response headers; otherwise, load the asset from your own origin or provide its bytes through a server-side flow.

Once you have image data, pass an explicit format such as 'PNG' when automatic type detection is uncertain. The format must describe the actual image encoding. A PNG data URL paired with 'JPEG' is a mismatch and may fail or render incorrectly. The image can be reused across page calls; you do not need to fetch or encode it again for every page.

3. Add the image to every page

This reusable helper draws the image on the existing first page, then creates and fills the remaining pages:

function addImageToPages(doc, imageData, options) {
  const {
    format = 'PNG',
    x,
    y,
    width,
    height,
    pageCount,
    alias
  } = options;

  if (!Number.isInteger(pageCount) || pageCount < 1) {
    throw new RangeError('pageCount must be an integer of at least 1');
  }

  for (let pageIndex = 0; pageIndex < pageCount; pageIndex += 1) {
    if (pageIndex > 0) {
      doc.addPage();
    }
    doc.addImage(imageData, format, x, y, width, height, alias);
  }
}

const doc = new jsPDF({ unit: 'mm', format: 'a4' });
const imageData = 'data:image/png;base64,...';

addImageToPages(doc, imageData, {
  format: 'PNG',
  x: 10,
  y: 20,
  width: 190,
  height: 100,
  pageCount: 5,
  alias: 'repeated-logo'
});

doc.save('five-pages.pdf');

The first loop iteration targets the document’s initial page. Later iterations create a page immediately before drawing. This avoids an unintended blank first page. If pageCount is one, the helper draws once and adds no extra page.

The optional alias identifies a reusable image. It can help when the same asset appears repeatedly. If your document contains different image data, give each distinct asset a distinct alias; do not assign one alias to unrelated images. The documentation describes addImage as adding an image to the PDF, and its parameters include coordinates, dimensions, alias, compression, and rotation. See the complete parameter reference.

4. Calculate dimensions and placement

The x and y coordinates and the width and height use the document unit selected when creating the PDF. The x coordinate is measured from the left edge; y is measured from the upper edge. If the page is A4 in millimeters, its dimensions are approximately 210 by 297 mm. Leave margins by positioning the image inside those page bounds.

Calculate placement in the PDF's units and preserve the source aspect ratio to avoid stretching.
Calculate placement in the PDF's units and preserve the source aspect ratio to avoid stretching.

Center an image without changing its aspect ratio

To fit an image inside a target box without stretching it, scale both dimensions by the same factor. The following assumes you know the source image’s pixel dimensions:

function fitInside(sourceWidth, sourceHeight, boxWidth, boxHeight) {
  const scale = Math.min(boxWidth / sourceWidth, boxHeight / sourceHeight);
  const width = sourceWidth * scale;
  const height = sourceHeight * scale;
  return { width, height };
}

const pageWidth = doc.internal.pageSize.getWidth();
const pageHeight = doc.internal.pageSize.getHeight();
const margin = 10;
const boxWidth = pageWidth - margin * 2;
const boxHeight = pageHeight - margin * 2;
const fitted = fitInside(1200, 800, boxWidth, boxHeight);
const x = (pageWidth - fitted.width) / 2;
const y = (pageHeight - fitted.height) / 2;

doc.addImage(imageData, 'PNG', x, y, fitted.width, fitted.height);

For example, the fit calculation can letterbox a landscape image in a portrait page: the image remains proportional and centered, with unused space around it. If instead you set both dimensions to fill the box regardless of the source ratio, the image may look stretched. If you need a full-bleed background, choose dimensions and placement for the page edges deliberately; printer margins and bleed requirements depend on the output workflow.

5. Choose page format, orientation, and page-specific placement

Call addPage(format, orientation) to add a page and make it active. jsPDF supports standard page formats and custom numeric dimensions. If every page uses the same size and orientation, calling addPage() inside the loop is enough. If page size changes, pass the intended format and orientation for each new page:

doc.addPage('a4', 'landscape');
doc.addImage(imageData, 'PNG', 10, 10, 277, 190);

These dimensions assume an A4 landscape page measured in millimeters with a 10 mm inset. Confirm the page dimensions for your chosen format and unit before using fixed placement values. Mixing portrait and landscape pages also means the same coordinates may no longer center or fit the image.

If you need to draw on a page you already created, use setPage(pageNumber). Page numbers start at 1:

doc.setPage(1);
doc.addImage(imageData, 'PNG', 10, 10, 50, 20);

This is useful when pages are built in stages, or when a final pass adds a logo or watermark to earlier pages. It selects an existing page; it does not create a new one.

6. Add a logo or watermark to an existing document

For a repeated header or watermark, run a page loop after the document’s content pages have been created. Read the current page count, select each page, and draw the asset:

const pageCount = doc.getNumberOfPages();
const logoX = 10;
const logoY = 8;
const logoWidth = 30;
const logoHeight = 10;

for (let pageNumber = 1; pageNumber <= pageCount; pageNumber += 1) {
  doc.setPage(pageNumber);
  doc.addImage(logoData, 'PNG', logoX, logoY, logoWidth, logoHeight, 'company-logo');
}

Choose a position that does not overlap page content, and check the first and last pages as well as any page with a different orientation. Repeatedly adding the same image to the same page overlays it at the same coordinates; it does not create a separate page.

7. Troubleshoot common problems

Symptom Likely cause Fix
Image appears only on page one The image was added only once, or later pages were created after the loop. Call addImage() after each addPage(), or select each existing page with setPage().
There is a blank first page The code called addPage() before drawing on the initial page. Draw on the initial page first. Start adding pages on loop iterations after the first.
Several copies overlap on one page The code calls addImage() repeatedly without changing the active page. Call addPage() between new pages, or call setPage(n) to select an existing page.
The image is stretched or clipped Pixel dimensions were treated as document units, or the requested box exceeds the page. Calculate dimensions in the selected PDF unit, preserve the source aspect ratio, and keep x + width and y + height within the page bounds.
jsPDF cannot process the image The supplied format does not match the bytes, the data URL is incomplete, or the browser could not fetch the image. Check the actual MIME type, ensure the image has fully loaded, and handle fetch errors or cross-origin restrictions before calling addImage().
A different image appears than expected Different image assets were assigned the same alias. Use a unique alias for each different image, or omit the alias when unnecessary.
Later pages use the wrong layout New pages were added with a different format or orientation than expected. Pass the required format and orientation to addPage(), then calculate placement for those page dimensions.
Watermark lands on the wrong page Page numbering was treated as zero-based. Use 1-based numbering with setPage(); a document’s first page is page 1.

8. Performance, reliability, and file size

Reusing one image data value avoids repeating image-loading and encoding work in your own loop. A repeated image still has to be represented in the PDF, and final size and memory use depend on image encoding, page count, and runtime. There is no single page-count or file-size limit that applies to every document, so measure with representative images and the browsers or server environments you support.

Large source images can make PDFs slow to generate and unnecessarily large. Resize assets to a sensible pixel size for their intended display dimensions, and prefer an appropriate format for the content: photographic images and logos with transparency have different needs. If the image is a photograph, JPEG can be suitable; PNG is often useful when transparency or sharp edges matter. Confirm the format passed to jsPDF matches the source data.

For reliable output, wait for asynchronous image loading to finish before generating the PDF, validate that the requested page count is a positive integer, and keep drawings within page bounds. When the output is user-facing or generated in bulk, handle fetch and PDF-generation errors explicitly and avoid constructing all the image data repeatedly for every page. Check a sample PDF in the viewers and print settings relevant to your users, since page scaling can vary outside the generated document.

Or skip the browser setup

If the image you need is a screenshot of a web page, [ScreenshotNeo](https://screenshotneo.com) can create the image through one API request; you can then place that image into a jsPDF document using the same repeated-page pattern above. See 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
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());

ScreenshotNeo removes cookie banners, popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, no card required.

Frequently asked questions

How do I add the same image to every page in jsPDF?

Draw it on page one, then repeat addPage() and addImage() for each additional page. Use the same image data and consistent coordinates if its placement should match.

Why does jsPDF only put my image on the first page?

Because image drawing applies to the active page. A call to addImage() does not automatically propagate to pages created later.

Can I add a logo to pages already in the PDF?

Yes. Loop through page numbers starting at 1, call setPage(pageNumber), and then call addImage() for each page.

Can I use a different image on each page?

Yes. Select or create the target page and pass that page’s image data to addImage(). Assign distinct aliases to different image assets if aliases are used.

Does jsPDF automatically scale an image to fit a page?

Provide the dimensions you want in the document’s units. Calculate a scale factor yourself when you need to preserve the source image’s aspect ratio or fit it inside margins.