Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →The usual fix is to separate capture resolution from PDF placement size. Start html2canvas at scale: 1, measure the resulting bitmap, then pass jsPDF dimensions in the PDF unit (such as millimetres), not in canvas pixels. Preserve the bitmap’s aspect ratio when calling addImage. A Retina display commonly makes html2canvas default to window.devicePixelRatio (often 2), so the bitmap can be twice as wide and tall as the CSS element. That is a resolution difference, not permission to enlarge the image in the PDF.
This guide uses “canvas2html” as a possible wrapper or local name for html2canvas. There is no canonical package identified as canvas2html; check which library your project actually imports before copying an option name.
Understand the four sizes before changing code
Zoomed exports happen when values from different coordinate systems are treated as interchangeable. Log all four of these measurements:
| Measurement | What it means | Typical unit | What can change it |
|---|---|---|---|
| Element CSS size | The layout box reported by the browser | CSS pixels | Styles, responsive layout, browser zoom and viewport width |
| Canvas bitmap size | The actual raster pixels in the canvas | Bitmap pixels | Element size multiplied by html2canvas scale |
window.devicePixelRatio |
Device backing-pixel ratio used by html2canvas by default | Ratio | Display density, operating-system scaling and browser zoom |
| jsPDF placement size | The rectangle reserved for the image on the PDF page | The PDF unit selected at construction | addImage coordinates, doc.html width and page margins |
For example, a 600 CSS-pixel element captured at scale 2 produces a canvas about 1,200 pixels wide. If you then call addImage(data, 'PNG', 10, 10, 600, ...) in a PDF created with unit: 'mm', the number 600 means 600 millimetres, not 600 pixels. That combination makes the image appear enormous.
Recommended Free Tools
#1 Best Overall
- EDIT text, images & designs in PDF documents. ORGANIZE PDFs. Convert PDFs to Word, Excel & ePub.
- READ and Comment PDFs – Intuitive reading modes & document commenting and mark up.
- CREATE, COMBINE, SCAN and COMPRESS PDFs
- FILL forms & Digitally Sign PDFs. PROTECT and Encrypt PDFs
- LIFETIME License for 1 Windows PC or Laptop. 5GB MobiDrive Cloud Storage Included.
Use a scale-1 baseline
- Capture the element with an explicit scale of one:
const canvas = await html2canvas(element, { scale: 1 });
- Compare
canvas.widthandcanvas.heightwith the element’s CSS dimensions. They should be close for a normal, unclipped capture. - Only increase
scaledeliberately when you need more raster detail. A scale of 2 quadruples the number of pixels and increases memory use; it does not require a larger PDF placement rectangle.
Do not “fix” a large PDF by dividing arbitrary numbers until it looks right. First identify whether the bitmap is already too large or whether jsPDF is receiving the wrong placement unit.
Complete html2canvas-to-jsPDF export
The following example captures one element, calculates a proportional height from the image itself, and places it inside 10-unit margins. The PDF uses millimetres, so every placement value is a millimetre value.
async function exportElement() {
const element = document.querySelector('#invoice');
if (!element) throw new Error('Missing #invoice element');
const css = element.getBoundingClientRect();
const canvas = await html2canvas(element, {
scale: 1,
useCORS: true,
backgroundColor: '#ffffff'
});
console.log({
cssWidth: css.width,
cssHeight: css.height,
bitmapWidth: canvas.width,
bitmapHeight: canvas.height,
devicePixelRatio: window.devicePixelRatio
});
const pdf = new jsPDF({ unit: 'mm', format: 'a4' });
const data = canvas.toDataURL('image/png');
const image = pdf.getImageProperties(data);
const margin = 10;
const pageWidth = pdf.internal.pageSize.getWidth();
const usableWidth = pageWidth - (margin * 2);
const usableHeight = image.height * usableWidth / image.width;
pdf.addImage(data, 'PNG', margin, margin, usableWidth, usableHeight);
pdf.save('export.pdf');
}
exportElement().catch(console.error);
getImageProperties returns the raster dimensions that jsPDF will use for the aspect-ratio calculation. The formula height = image.height * width / image.width prevents stretching. If the content is taller than one page, the proportional height is still correct; you must then paginate or render sections rather than force the entire image into a page.
Keep doc.html width separate from raster scale
jsPDF’s HTML API exposes two different controls. The nested html2canvas options determine how the browser rasterizes the content. The width option determines the target fit in PDF units. The documented behavior is that target width has no effect when html2canvas.scale is explicitly specified.
Free tools Windows power users keep installed
One-click scans. No signup required.
const pdf = new jsPDF({ unit: 'mm', format: 'a4' });
await pdf.html(document.querySelector('#invoice'), {
margin: [10, 10, 10, 10],
width: 190,
html2canvas: {
scale: 1,
useCORS: true
},
callback: (doc) => doc.save('html-export.pdf')
});
Choose one policy and document it in your code: either let doc.html fit the content by its PDF width, or explicitly control the html2canvas scale and place the resulting image yourself. Mixing a device-pixel scale with pixel-like PDF numbers is the common source of apparent zoom.
Account for browser zoom and display density
Browser zoom and operating-system display scaling can alter the relationship between CSS pixels and physical pixels. html2canvas’s default scale is window.devicePixelRatio, so the same page can produce different bitmap dimensions on different screens. A fixed scale: 1 makes the export’s raster dimensions deterministic relative to the CSS layout, although responsive CSS can still change when the viewport width changes.
If you intentionally want sharper output, choose a known scale and keep PDF placement based on the image’s aspect ratio:
Rank #2
- Edit PDFs with Ease. Modify text, images, and layouts directly within your PDF documents.
- Convert & Organize. Export PDFs to Word, Excel, or ePub, and organize files with ease.
- Read & Annotate. Enjoy intuitive reading modes and powerful tools to comment, highlight, and mark up PDFs.
- Create & Manage PDFs. Create new PDFs, combine multiple files, scan documents, and compress for easy sharing.
- Fill & Sign Forms. Complete forms and digitally sign documents with secure e-signature tools.
const scale = 2; // intentional quality choice, not a PDF size
const canvas = await html2canvas(element, { scale });
const data = canvas.toDataURL('image/png');
const props = pdf.getImageProperties(data);
const width = 190;
const height = props.height * width / props.width;
pdf.addImage(data, 'PNG', 10, 10, width, height);
Do not use screen.width or a monitor’s physical resolution to calculate PDF dimensions. Use the element’s layout dimensions for capture and the PDF page’s units for placement.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsLoad remote images without tainting the canvas
Images from another origin can be skipped or make the canvas unreadable under browser security rules. useCORS: true works only when the image server sends the appropriate CORS response header. If it does not, serve the asset from the same origin or fetch it through a server-side proxy that you control.
const canvas = await html2canvas(element, {
scale: 1,
useCORS: true,
imageTimeout: 15000
});
Make sure images are loaded before starting the capture. A CORS option cannot repair a server that does not grant cross-origin access, and converting the canvas to a data URL will fail if the bitmap has already been tainted.
Prevent clipping on long or responsive pages
A very tall element can exceed browser canvas limits even when the JavaScript is correct. If the bottom is missing, capture page-sized sections instead of one giant bitmap. For a responsive component, set capture dimensions to its scrollable size:
const width = element.scrollWidth;
const height = element.scrollHeight;
const canvas = await html2canvas(element, {
scale: 1,
windowWidth: Math.max(window.innerWidth, width),
windowHeight: Math.max(window.innerHeight, height),
width,
height
});
For multi-page PDFs, render a header and each content slice separately, or use jsPDF’s HTML pagination features. Never compensate for clipping by enlarging the remaining image.
Audit drawImage source rectangles
Custom canvas code can enlarge or crop an image before jsPDF ever sees it. When calling drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight), verify that the source rectangle describes the intended pixels and that destination dimensions are in the canvas coordinate system. jsPDF’s context2d implementation applies separate clipping and scale factors, so a source rectangle that is too small or a destination rectangle that is too large produces a genuine zoom.
- For a full-image copy, omit the source rectangle and provide only destination coordinates and size.
- Keep source width and height proportional to destination width and height.
- Log every rectangle when the exported image is cropped or magnified.
Diagnostic checklist
- Log
getBoundingClientRect(), canvas dimensions andwindow.devicePixelRatio. - Run once with
scale: 1and browser zoom at 100 percent. - Confirm the PDF’s unit in
new jsPDF({ unit: ... }). - Inspect every
addImagewidth and height; they are PDF units, not pixels. - Calculate one dimension from the other using the image properties.
- Test with local, same-origin images before debugging CORS.
- Capture a short element before attempting a full document.
- Check custom
drawImagesource and destination rectangles.
Common symptoms and precise fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Bitmap width and height are exactly about twice the CSS size | Default scale follows a Retina devicePixelRatio of 2 |
Set scale: 1, or keep scale 2 intentionally and size the PDF from image properties |
| Bitmap dimensions look correct, but the PDF is huge | Pixel values were passed as millimetres, points or inches | Use the PDF page width in its declared unit and calculate the proportional height |
| Image is stretched | Independent width and height values were supplied | Derive height from props.height * width / props.width |
Remote images disappear or toDataURL throws a security error |
Missing CORS header or cross-origin canvas taint | Use useCORS: true with a correctly configured server, or use a same-origin proxy |
| Bottom of a long page is missing | Canvas or browser dimension limit | Match capture dimensions to scroll dimensions and split content into page-sized sections |
| Only a selected region is enlarged or cropped | Incorrect sx, sy, sWidth or sHeight |
Log the source rectangle and make destination dimensions proportional |
| Output changes between monitors | Implicit device-pixel scaling or responsive layout | Set an explicit scale and a controlled viewport; avoid monitor pixels in PDF calculations |
Quality, speed and memory trade-offs
Scale is a quality setting. Increasing it can make text and fine lines sharper, but pixel count and memory grow rapidly. Start at 1, compare the result at the final PDF viewing size, and increase only if detail is genuinely insufficient. Prefer JPEG for photographic content when file size matters, and PNG for diagrams, text and transparency. A transparent PDF background is not automatic: choose the html2canvas background behavior and the PDF image format deliberately.
Rank #3
- EVERY PDF TOOL UNLOCKED - 30+ tools in one app: edit text and images, convert, merge, split, compress, sign, OCR, redact, watermark, batch process, and more. No feature gates, no upsells, nothing held back.
- PAY ONCE, OWN FOREVER — A one-time purchase, not a subscription. Other apps runs $240/year — Scrivar is yours for life, with free updates included.
- UNLIMITED eSIGN, BUILT IN — Send contracts and forms for signature and track every step. Recipients sign in their browser with no account or app needed. Replace DocuSign and save hundreds a year.
- PC, MAC, AND WEB — Install on any Win 10/11 PC or macOS 11+ Mac (Intel or Apple Silicon), or work in your browser at scrivar.com. Same tools, same account, everywhere you work.
- OCR + FULL OFFICE CONVERSION — Turn scanned documents into searchable, selectable text, and convert PDFs to and from Word, Excel, and PowerPoint with formatting kept intact.
Large pages should be segmented. Smaller captures reduce peak memory, make retries practical and let you identify the exact section that fails. Wait for fonts, images and application data to settle before capture; otherwise a correctly sized canvas can still contain incomplete content.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server when you need a rendered page rather than a hand-tuned browser pipeline. One GET request returns PNG, JPEG, WebP or PDF. Before capture it accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks, 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.
Use the documented API parameters and options for full-page captures, lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and margins, custom CSS or JavaScript, click and wait actions, request blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and the OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify a migration.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
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)
Node.js
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(`${res.status} ${res.statusText}`);
const bytes = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', bytes);
See the ScreenshotNeo API documentation for parameter details. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account to try it.
Frequently Asked Questions
Does setting html2canvas scale to 1 reduce CSS dimensions?
No. It changes the raster pixel density only; the captured layout remains based on the element and viewport CSS dimensions.
Should I divide addImage dimensions by devicePixelRatio?
Not as a general rule. Choose PDF-unit dimensions from the page geometry and preserve the image aspect ratio; devicePixelRatio belongs to capture resolution.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Can useCORS bypass a server’s access policy?
No. The image server must send a suitable CORS header, or the asset must be same-origin or proxied.
Why does a full-page capture fail only on very long documents?
Browser canvas dimensions and memory are finite. Split the document into page-sized captures and place those sections on separate PDF pages.
Quick Recap
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.

