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

Two different settings cause the symptoms in the Angular 6 example: a data URL has no download filename because it is being assigned to window.location.href, while the PDF remains A4 because new jspdf('p', 'mm', 'a4') explicitly requests A4. Give the image an anchor with a download filename, and create the PDF with custom page dimensions that match the card you want to print. If images disappear, check cross-origin permissions before changing export code.

Fix the PNG download filename

canvas.toDataURL('image/png') produces a PNG data URL. It contains image bytes and a MIME type, but it does not contain a filesystem name. Navigating to that URL, including after changing its MIME string to image/octet-stream, leaves filename handling to the browser.

Use an anchor instead. Set its download property to a name ending in .png (or .jpg when exporting JPEG), assign the data URL to href, and click it.

html2canvas(element).then(canvas => {
  const link = document.createElement('a');
  link.download = 'card.png';
  link.href = canvas.toDataURL('image/png');
  link.click();
});

This is the documented html2canvas download pattern. Do not replace a PNG data URL with image/octet-stream when the goal is a predictable image file. A browser or security context can still apply its own download rules, but the anchor supplies the intended filename.

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

Angular component example

import html2canvas from 'html2canvas';

export class CardComponent {
  downloadCard(): void {
    const element = document.getElementById('card');
    if (!element) {
      throw new Error('Card element was not found');
    }

    html2canvas(element).then(canvas => {
      const link = document.createElement('a');
      link.download = 'card.png';
      link.href = canvas.toDataURL('image/png');
      link.click();
    });
  }
}

The exact import form depends on the html2canvas version installed by the Angular 6 project. Check package.json and package-lock.json and use that version’s documentation; a current example does not prove compatibility with a 2018 dependency.

Why the PDF is A4

The original constructor asks jsPDF for portrait A4 in millimetres:

const pdf = new jspdf('p', 'mm', 'a4');

The later imgWidth = 208 assignment changes only the image’s placement width. It cannot change the page format. The proportional height calculation preserves the captured image’s aspect ratio, but it does not make the page the same size as the card.

Choose a physical page size first

A PDF page has physical units; a canvas has pixels. Decide the desired page width and height in one unit, then place the raster image inside those bounds. Do not treat 208 mm as a standard card measurement: it was simply a value in the reported code, and the intended card dimensions were not supplied.

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.

Custom format with the options object

import { jsPDF } from 'jspdf';

html2canvas(element).then(canvas => {
  const pdf = new jsPDF({
    orientation: 'landscape',
    unit: 'mm',
    format: [100, 60]
  });

  const pageWidth = 100;
  const pageHeight = 60;
  const imageRatio = canvas.width / canvas.height;
  const pageRatio = pageWidth / pageHeight;

  let imageWidth;
  let imageHeight;
  let x;
  let y;

  if (imageRatio > pageRatio) {
    imageWidth = pageWidth;
    imageHeight = pageWidth / imageRatio;
    x = 0;
    y = (pageHeight - imageHeight) / 2;
  } else {
    imageHeight = pageHeight;
    imageWidth = pageHeight * imageRatio;
    y = 0;
    x = (pageWidth - imageWidth) / 2;
  }

  pdf.addImage(canvas.toDataURL('image/png'), 'PNG', x, y,
               imageWidth, imageHeight);
  pdf.save('card.pdf');
});

Replace [100, 60] with the physical dimensions you actually need. This “contain” calculation preserves the card’s proportions and may leave white margins. Filling the page by stretching distorts text and graphics; cropping fills the page but removes content. Choose deliberately.

Legacy constructor form

Older jsPDF releases may use the positional constructor. The equivalent concept is:

const pdf = new jspdf('l', 'mm', [100, 60]);

Whether this signature is available in the Angular 6 project’s installed version must be verified against its package version. Current jsPDF documentation also shows an options object such as new jsPDF({ orientation: 'landscape', unit: 'in', format: [4, 2] }); current documentation alone does not establish compatibility with the historical dependency.

Relate canvas pixels to PDF size

html2canvas captures pixels. jsPDF interprets the width and height supplied to addImage in the document unit you selected. A larger canvas gives more raster detail at the same physical size; it does not automatically create a larger paper page. If the capture is too small, increase the capture scale where supported by your installed html2canvas version, or render a suitably large element, then keep the PDF dimensions fixed.

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

For a CSS card that is 400 by 240 CSS pixels, you must still choose a physical output size—for example, 100 by 60 mm. The pixel-to-millimetre conversion is an output decision, not a property html2canvas can infer reliably. Preserve the ratio 400:240 (5:3) when fitting the image.

Images missing from the canvas: CORS diagnosis

Browsers protect canvases from cross-origin resources. html2canvas may skip an image that would taint the canvas. useCORS: true helps only when the image server responds with an appropriate Access-Control-Allow-Origin header.

html2canvas(element, {
  useCORS: true
}).then(canvas => {
  // export canvas here
});

Three hosting choices

  • Same origin: Serve the page and images from the same scheme, host and port. This is usually the simplest arrangement.
  • Cross origin with CORS: Configure the image server to return an allowed origin, then use useCORS: true.
  • Same-origin proxy: Fetch the asset through your own server and expose it from the application’s origin when you cannot change the remote server.

html2canvas cannot circumvent browser content-policy restrictions. allowTaint is not a fix that makes a tainted canvas safely readable for export. Inspect the browser network panel for the image response and its CORS headers.

Blank, clipped or visually different captures

Viewport and scrolling

If a long card is clipped, the clone may be using viewport dimensions rather than the element’s full scroll area. Try dimensions based on the element:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const rect = element.getBoundingClientRect();
html2canvas(element, {
  windowWidth: element.scrollWidth || Math.ceil(rect.width),
  windowHeight: element.scrollHeight || Math.ceil(rect.height)
});

Use the exact option names supported by your installed version. Very large canvases can exceed browser or device limits; those limits vary by browser, platform and hardware, so there is no universal safe megapixel threshold. Capture a smaller region, reduce scale, or split a very large export.

Unsupported CSS

html2canvas rebuilds a representation by traversing the DOM and reading implemented style information; it is not a literal screenshot. CSS properties that the library does not implement can differ from what you see on screen. Simplify unsupported effects, provide fallback styles, or use a browser-level screenshot service when pixel fidelity is essential.

Reliable export sequence

  1. Wait until the card’s data and web fonts have loaded.
  2. Confirm every image URL works in the browser and decide whether it is same-origin, CORS-enabled or proxied.
  3. Capture the intended element, accounting for its full scroll dimensions.
  4. For an image, create an anchor and set an explicit filename.
  5. For a PDF, select physical page dimensions, preserve the image ratio, and place the image with deliberate margins.
  6. Test a small card and a card containing remote images before exporting large pages.

Common errors and fixes

Symptom Likely cause Fix
File downloads without .png Data URL was navigated to directly Use an anchor with download = 'card.png'.
PDF is always A4 Constructor contains 'a4' Pass a custom [width, height] format.
Image absent in canvas Remote response lacks CORS permission Use same-origin hosting, configure CORS, or proxy the asset.
Blank or partial canvas Oversized canvas or viewport-sized clone Reduce capture size/scale and set appropriate window dimensions.
Effects differ from the page CSS is not implemented by html2canvas Use supported styles or a browser screenshot approach.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status.

One GET request returns PNG, JPEG, WebP or PDF. The API supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper size and margins, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification.

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

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

See the ScreenshotNeo documentation for authentication and capture parameters. The Free plan includes 1,000 screenshots each month without a card; paid plans start at $5 for 3,000 shots. An MCP server lets Claude, Cursor and other MCP clients call take_screenshot, get_page_info and capture_pdf.

Create a free ScreenshotNeo account to try the 1,000 monthly screenshots.

Frequently Asked Questions

Can I make a PDF exactly the same physical size as a CSS card?

Yes, but you must choose a CSS-to-physical conversion and pass the resulting width and height as the custom PDF format; the browser cannot infer your preferred paper size.

Will useCORS fix every missing image?

No. It works only when the remote image response grants the requesting origin with an appropriate CORS header; otherwise use same-origin hosting or a proxy.

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.

Why does the PDF look blurry even when the page size is correct?

The PDF contains a raster canvas. Increase capture resolution within browser limits or reduce the physical output size while preserving the card ratio.

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.