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

Most jsPDF HTML-to-PDF failures fall into one of four stages: dependencies or runtime are missing, the browser cannot load an asset, html2canvas cannot reproduce a CSS effect, or the resulting canvas and PDF pagination are too large or poorly configured. Start with a small client-side reproduction, then troubleshoot the failing stage rather than changing PDF options at random. The steps below cover blank output, missing images, CSS differences, clipped pages, broken glyphs, and server-side rendering.

First, confirm the conversion path

jsPDF’s html() method accepts an HTMLElement or an HTML string. It uses the optional html2canvas dependency to render HTML; when you pass a string, dompurify is also involved. A missing dependency or failed dynamic import can look like a rendering problem, so verify the installed package and build output before changing layout settings. See the jsPDF HTML API documentation and the jsPDF project documentation.

Reduce the input to one small, visible element and use the callback to save the generated document:

const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const element = document.querySelector('#receipt');

if (!element) throw new Error('Could not find #receipt');

doc.html(element, {
  callback: (pdf) => pdf.save('output.pdf')
});

This example assumes a browser page where jsPDF is exposed as window.jspdf. If your app imports packages as modules, import jsPDF according to your bundler and installed package version instead. The callback runs after HTML rendering completes; if the PDF is not saved, inspect the browser console and the network/build output for dependency errors. Keep testing in the browser: html2canvas requires window, document, and computed styles.

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

Pass an element or a string deliberately

An element is usually the simpler diagnostic input because it lets you inspect the rendered DOM directly. If you pass an HTML string, make sure the string path’s DOMPurify dependency is available, and sanitize any user-controlled content. The jsPDF project documentation says: “We strongly advise you to sanitize user input before passing it to jsPDF!” Do not treat sanitization as a substitute for safe application design.

Why images are missing

Check the image request in the browser’s developer tools first. A missing file, blocked request, or browser cross-origin restriction can keep an image out of the canvas even while the rest of the PDF renders. html2canvas’s FAQ explains that cross-origin images may taint a canvas and are skipped when allowTaint is false, its default. JavaScript cannot override the browser’s content policy.

Choose the loading path that fits the image

  • Same-origin image: Prefer a URL served from your site. Confirm that the request succeeds before invoking doc.html().
  • Cross-origin image with server permission: Set useCORS: true in the html2canvas options only if the image server returns an appropriate Access-Control-Allow-Origin response header.
  • Cross-origin image without CORS permission: If you control an appropriate server-side proxy and its use is permitted, load the image through that same-origin proxy. A proxy does not make restricted or unauthorized content available by magic.

Use the rendering options to expose failures while diagnosing:

doc.html(element, {
  callback: (pdf) => pdf.save('output.pdf'),
  html2canvas: {
    useCORS: true,
    logging: true,
    onError: (error) => console.error('html2canvas resource error:', error)
  }
});

Confirm that the installed html2canvas version supports the options you use; the html2canvas configuration reference documents its configuration. useCORS asks the browser rendering path to use CORS-enabled image loading; it does not grant permission if the remote server omits the required header.

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

Why the PDF does not match the webpage

html2canvas is not a native browser screenshot. It walks the DOM and reconstructs a rendering from supported DOM and style information, so a successful PDF can still look different from the screen. The html2canvas documentation describes this approach and its limitations.

When one CSS property appears absent or only partly applied, reduce the page to the affected element and check the project’s supported features. Simplify unsupported effects, then add styles back one at a time. Treat the output as a rendering by html2canvas, not proof that a browser’s visual compositor has been captured exactly.

Check embedded frames separately

A browser does not let page JavaScript read a cross-origin iframe’s document, so html2canvas cannot reconstruct its contents. Same-origin iframes are documented as supported; cross-origin content is not available to the parent page through this route. If the frame matters, render its content in a context you are authorized to access or omit it from the HTML being converted.

Fix blank, oversized, or truncated output

A blank or partially drawn canvas can result from canvas dimensions or total area exceeding what a particular browser, operating system, GPU, or device can handle. These limits vary, and an oversized canvas may fail without a useful exception. Do not rely on a single maximum-size figure as a guarantee across users’ devices.

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.
  1. Reduce the capture region. Temporarily render one section or a shorter document. If that works, the full-page canvas is putting too much pressure on the browser.
  2. Lower the rendering scale. Try a smaller html2canvas.scale value to reduce the canvas dimensions. This can reduce sharpness, so use the highest value that works for the document and target devices.
  3. Match the virtual viewport to the element. If content is clipped because html2canvas is using the wrong viewport dimensions, set windowWidth and windowHeight to match the element’s scroll dimensions. Do not apply this blindly: viewport changes can also affect responsive CSS and therefore the layout.
  4. Retest with the real content. Long pages, high-resolution images, and device differences can change the result. Check the smallest and largest expected documents in the browsers and devices you support.
const width = element.scrollWidth;
const height = element.scrollHeight;

doc.html(element, {
  callback: (pdf) => pdf.save('output.pdf'),
  html2canvas: {
    scale: 1,
    windowWidth: width,
    windowHeight: height,
    logging: true
  }
});

Here, scale: 1 is an explicit starting point, not a universal optimum. If output remains blank or is too large, test a lower scale and smaller regions. Verify option names against the html2canvas version installed in your application; its configuration reference describes the available settings.

Choose pagination for the content

jsPDF’s html() pagination defaults to automatic paging. Its autoPaging option offers modes suited to different layouts; the API documentation describes 'slice' and 'text' as distinct choices.

Mode What it does When to try it
'slice' Slices rendered content to fit pages and can cut through text at a page boundary. Content where slicing is acceptable or text continuity is less important.
'text' Tries to avoid splitting text; the API documentation says it is best suited to mostly single-column documents. Text-heavy, mostly single-column pages where keeping text together matters.
true (default) Uses automatic paging. Start here for the standard path, then choose a mode if the page breaks are unsuitable.

For example, test text-aware paging and adjust margins and output width to fit the content:

doc.html(element, {
  callback: (pdf) => pdf.save('output.pdf'),
  margin: [12, 12, 12, 12],
  autoPaging: 'text',
  width: 186
});

The example uses millimetre-style dimensions commonly used with jsPDF’s default paper setup; confirm units and paper format for your document. Inspect tables, positioned elements, and large blocks individually: no paging mode can infer every document’s intended break points. The HTML API reference lists the method’s margin, pagination, width, image, html2canvas, font-face, and positioning options.

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

Repair missing or garbled characters

jsPDF’s 14 standard PDF fonts are limited to the ASCII codepage. If the text needs characters outside that set, missing glyphs can appear garbled or absent. Embed a TrueType font (TTF) that contains the required characters and make it available to jsPDF. The fontFaces option on html() lets you provide font-face information for resolving fonts during HTML rendering; consult the API documentation for the option’s expected structure in your installed version.

Test with the actual characters that fail—not just ordinary Latin text—and confirm that the selected font file includes their glyphs. If the browser page itself falls back to another font, the PDF renderer may also resolve differently than expected.

Know where the conversion can run

The HTML rendering stage cannot run in plain Node.js because html2canvas depends on browser APIs such as window, document, and computed styles. jsPDF does offer a Node build for PDF operations, but that does not add a browser DOM to html2canvas. For server-side HTML rendering, html2canvas’s FAQ points to driving a real browser with Puppeteer or Playwright.

On Node, jsPDF restricts local filesystem reads by default and documents Node permission flags as the stronger enforcement mechanism. Do not pass untrusted HTML or assume that running the PDF library server-side makes unsafe input harmless. See the jsPDF project documentation for its security guidance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a screenshot of a live webpage rather than a PDF generated from your app’s DOM, a screenshot API is a different route. ScreenshotNeo returns a screenshot or PDF from one GET request. The cURL example below saves the response as a WebP image; replace the URL with the page you want and use your API key. See the ScreenshotNeo API docs for 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
  • Cookie and consent banners, newsletter popups, and chat widgets are removed before capture; each step can be turned off.
  • Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; the response reports the page verdict and billing status in headers.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

ScreenshotNeo is not a replacement for rendering arbitrary HTML from your application: use jsPDF or a browser-rendering workflow when you need to convert your own DOM or control a generated document. For live-page captures, ScreenshotNeo is an alternative. Sign up for 1,000 free screenshots a month with no card.

Quick troubleshooting checklist

Symptom Likely cause First fix
No PDF or conversion error Missing optional dependency, failed dynamic import, or absent element. Confirm the element exists; check console/build output and ensure html2canvas is available. For string input, check DOMPurify too.
PDF renders but image is absent Failed request, CORS restriction, or inaccessible resource. Inspect the request and response headers; use same-origin loading, permitted CORS, or an appropriate proxy.
Style differs from browser Unsupported or partially supported CSS in html2canvas. Check supported features and simplify the affected styling.
Canvas is blank or cut off Canvas size pressure or mismatched viewport dimensions. Capture less content, reduce scale, and test matching window dimensions.
Text is split at page edges Pagination mode does not fit the content. Try autoPaging: 'text' for mostly single-column text and inspect complex blocks.
Non-Latin characters are missing Standard PDF font encoding lacks required glyphs. Embed a TTF font with those characters and configure font faces.
Works in browser, fails in Node html2canvas needs browser DOM APIs. Run the render in a browser or automate a browser for server-side work.

Option names and dependency behavior can change between releases. The jsPDF API documentation reports generation on 2026-03-17, while the html2canvas FAQ and configuration pages are not pinned to a release; compare their options with your installed versions before debugging a version-specific failure.

Frequently Asked Questions

Can jsPDF’s html() method make a native screenshot of a webpage?

No. It renders a reconstruction from DOM and supported style information through html2canvas; it does not capture the browser’s native visual output.

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.

Will setting useCORS to true make every remote image appear?

No. The image server must permit the request with a suitable Access-Control-Allow-Origin header; otherwise use a permitted same-origin route or omit the image.

Can I use jsPDF html() directly in a Node.js process?

Not for the html2canvas rendering stage. That stage needs browser APIs; use a browser context for HTML rendering.

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.