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

html2canvas does not save a file by itself. It returns a Promise that resolves to an HTMLCanvasElement. To store the result, export that canvas as a PNG data URL for a simple browser download, or create a Blob with toBlob() when the image is large or must be uploaded. The download happens entirely in the browser; no server is required for a local copy.

What html2canvas actually returns

Calling html2canvas(element) asks the browser to reconstruct the selected DOM element as a canvas. The call is asynchronous, so your saving code belongs in the Promise callback (or after await). The canvas is an in-memory object, not a file path and not persistent storage. Exporting it is a separate step.

html2canvas(document.querySelector('#invoice')).then(canvas => {
  // Export the canvas here.
});

The library runs in the browser and can capture the whole document or a particular element. It is not a native browser screenshot: it traverses the DOM and draws a representation from properties it understands. Unsupported CSS, browser-rendered effects, and other implementation details can therefore look different from the live page.

Download a PNG with the simplest method

For a normal-sized image and a one-off local download, convert the canvas to a data URL, put it in an anchor, set the filename, and trigger a click.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Seagate 2TB Portable Hard Drive | USB 3.0 (STGX2000400)
  • Easily store and access 2TB to content on the go with the Seagate Portable Drive, a USB external hard drive
  • Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop
  • To get set up, connect the portable hard drive to a computer for automatic recognition no software required
  • This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
  • The available storage capacity may vary.
html2canvas(document.body).then(canvas => {
  const link = document.createElement('a');
  link.download = 'screenshot.png';
  link.href = canvas.toDataURL('image/png');
  link.click();
});

A complete page example looks like this. Load html2canvas before the script, give the capture area an ID, and click the button after the page has rendered.

<button id="save-shot" type="button">Save screenshot</button>
<main id="capture">
  <h1>Quarterly report</h1>
  <p>This content will be rendered into the image.</p>
</main>

<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
<script>
  document.querySelector('#save-shot').addEventListener('click', async () => {
    const element = document.querySelector('#capture');
    const canvas = await html2canvas(element);
    const link = document.createElement('a');
    link.download = 'quarterly-report.png';
    link.href = canvas.toDataURL('image/png');
    link.click();
  });
</script>

The download attribute supplies the suggested name. The browser decides how the download is presented, so a user may still be asked where to save it or may have downloads routed to the browser’s configured folder.

Use toBlob() for large images and uploads

toDataURL() encodes the entire image into one in-memory string. That is convenient, but a large canvas can consume substantial memory and the resulting URL can be impractically long. toBlob() creates a binary Blob, which is a better handoff for a large download or an upload.

html2canvas(document.querySelector('#capture')).then(canvas => {
  canvas.toBlob(blob => {
    if (!blob) {
      console.error('The browser could not encode the canvas.');
      return;
    }

    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.download = 'screenshot.png';
    link.href = url;
    link.click();

    // Release the temporary object URL after the browser has started the download.
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  }, 'image/png');
});

The callback can receive null if encoding fails, so production code should check it. Revoke the object URL when it is no longer needed; otherwise repeated captures can leave temporary resources referenced in memory.

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

Choose an export format

Format Best use Important behavior
PNG Interfaces, text, diagrams, and transparency The dependable default and required canvas export format.
JPEG Photographic or very large images where a smaller file is useful Lossy; a quality value from 0 to 1 can be supplied where the browser supports it.
WebP Smaller modern image files when your target browsers support encoding Support is browser-dependent; do not assume every browser can encode WebP.

For JPEG, pass a quality value as the third argument to toBlob() or toDataURL():

Rank #2
Seagate Portable 1TB External Hard Drive HDD – USB 3.0 for PC, Mac, PlayStation, & Xbox, 1-Year Rescue Service (STGX1000400) , Black
  • Easily store and access 1TB to content on the go with the Seagate Portable Drive, a USB external hard drive.Specific uses: Personal
  • Designed to work with Windows or Mac computers, this external hard drive makes backup a snap just drag and drop. Reformatting may be required for Mac
  • To get set up, connect the portable hard drive to a computer for automatic recognition no software required
  • This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable
  • The available storage capacity may vary.
canvas.toBlob(blob => {
  if (blob) {
    // use the JPEG Blob
  }
}, 'image/jpeg', 0.85);

PNG is the safest choice when you do not control the browser or need crisp text. Changing formats does not fix a tainted canvas; cross-origin assets must be handled first.

Upload the screenshot or keep durable storage

A browser download is local and temporary from your application’s point of view. If users must retrieve the image later, send the Blob to a server or storage system selected by your application. The server endpoint, authentication, retention policy, and provider are architecture decisions; html2canvas only creates the image payload.

async function captureAndUpload() {
  const canvas = await html2canvas(document.querySelector('#capture'));
  const blob = await new Promise(resolve =>
    canvas.toBlob(resolve, 'image/png')
  );

  if (!blob) throw new Error('Canvas encoding failed');

  const form = new FormData();
  form.append('screenshot', blob, 'capture.png');

  const response = await fetch('/your-upload-endpoint', {
    method: 'POST',
    body: form
  });

  if (!response.ok) {
    throw new Error(`Upload failed: ${response.status}`);
  }

  return response.json();
}

Replace /your-upload-endpoint with an endpoint you control. Do not put a secret storage credential in browser JavaScript. Validate the received MIME type and size on the server, and decide how long uploaded captures should remain available.

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

Capture the right element and wait for the page

Capture one region

Pass a specific element instead of document.body when the file should contain only a card, report, or component.

const element = document.querySelector('.receipt');
const canvas = await html2canvas(element);

Make sure fonts, images, and dynamic data have finished loading before calling html2canvas. If your page fills content after a network request, call the capture function after that request and after the relevant images are ready; otherwise the canvas can faithfully reproduce an incomplete page.

Rank #3
Sale
WD 2TB Elements Portable External Hard Drive for Windows, USB 3.2 Gen 1/USB 3.0 for PC & Mac, Plug and Play Ready - WDBU6Y0020BBK-WESN
  • High capacity in a small enclosure – The small, lightweight design offers up to 6TB* capacity, making WD Elements portable hard drives the ideal companion for consumers on the go.
  • Plug-and-play expandability
  • Vast capacities up to 6TB[1] to store your photos, videos, music, important documents and more
  • SuperSpeed USB 3.2 Gen 1 (5Gbps)

Use a predictable filename

Build names from safe characters and a meaningful identifier, such as invoice-1042.png. Avoid putting unsanitized user input directly into a filename.

Cross-origin images, iframes, and blank exports

Cross-origin images can taint the canvas

Images loaded from another origin can make the canvas unsafe to read. A subsequent export may be blank or throw a SecurityError. html2canvas documents a useCORS option and a proxy option for resources that cannot be loaded same-origin.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const canvas = await html2canvas(document.querySelector('#capture'), {
  useCORS: true
});

useCORS is useful only when the image server permits the browser’s cross-origin request. If it does not, route the resource through a proxy that you operate and configure html2canvas to use that proxy. A proxy must fetch the asset server-side and return it with the headers your page needs; simply turning on useCORS cannot grant access that the remote server has denied.

Cross-origin iframes are a hard boundary

html2canvas cannot render a cross-origin iframe because the page is not allowed to access that iframe’s contentDocument. You can capture the surrounding page, but the foreign document itself must be rendered by code running in its own origin or captured by a separate service.

Why the result differs from a browser screenshot

The library reconstructs the image from the DOM rather than asking the browser for a native bitmap. CSS or browser-rendered details that it does not understand may be missing or visually different. Treat the output as a DOM-based rendering, not a pixel-perfect replacement for a DevTools or operating-system screenshot.

Performance and reliability checklist

  • Prefer toBlob() for large canvases. It avoids assembling the complete image in a giant data URL string.
  • Release object URLs. Call URL.revokeObjectURL() after a download or upload no longer needs the URL.
  • Capture only what you need. A focused element uses less memory than an entire long document.
  • Handle failures explicitly. Check for a null Blob, catch rejected Promises, and report upload HTTP errors.
  • Do not assume every format works everywhere. PNG is the reliable baseline; JPEG and WebP encoding depend on browser support.
  • Protect user data. A screenshot can contain private text or images. Treat downloaded files and uploaded Blobs as sensitive application data.
async function saveCapture() {
  try {
    const canvas = await html2canvas(document.querySelector('#capture'));
    const blob = await new Promise(resolve =>
      canvas.toBlob(resolve, 'image/png')
    );
    if (!blob) throw new Error('No image Blob was produced');

    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'capture.png';
    document.body.appendChild(link);
    link.click();
    link.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  } catch (error) {
    console.error('Screenshot failed', error);
  }
}

Troubleshooting common failures

The downloaded file is blank

Check whether images came from another origin, whether a cross-origin iframe is inside the capture, and whether the capture ran before dynamic content loaded. Enable useCORS only when the image host allows it; otherwise provide a suitable proxy. Capture a smaller, same-origin element to isolate the offending asset.

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

The browser throws SecurityError

This usually indicates a tainted canvas caused by cross-origin content. Remove or proxy the foreign asset, or configure it for CORS. Exporting with a different format will not bypass the browser’s origin rules.

toBlob() returns null

Keep the null check and show a recoverable error. Retry after reducing the capture area or use PNG as the baseline format. If the canvas itself is invalid because of origin restrictions, fix that underlying problem first.

The image looks different from the page

That is expected when the page uses CSS or browser-rendered features outside html2canvas’s supported representation. Simplify the captured component, verify the DOM styles, or use a native browser capture service when pixel-level fidelity is a requirement.

The download works once but later captures consume memory

Repeated data URLs and unreleased object URLs keep large strings or Blob references alive. Use the Blob workflow, revoke each object URL, and avoid retaining old canvases in application state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
Sale
UnionSine 1TB Ultra Slim Portable External Hard Drive HDD-USB 3.0
  • 【Upgraded version】 - The mirror logo strip is combined with the striped non-slip design. The rounded corners of the shell are more suitable for holding. The strips play a heat dissipation function to ensure a stable and fast transmission process.
  • 【Ultra-thin and quiet】 - The motherboard adopts JMicron 578 noise-free solution, giving you a quiet working environment. Lightweight and portable size designed to fit in your pocket for easy portability.
  • 【Ultra-Fast Data Transfers】 - Pairing this external hard drive with JMicron 578 solution USB 3.0 and USB 2.0 interfaces enables blazing-fast data transfer. It boasts theoretical read speeds of up to 125MB/s and write speeds of up to 103MB/s.
  • 【Plug and Play】 - With no software to install, just plug it in and the drive is ready to use.The hard disk chip is wrapped with an aluminum anti-interference layer to increase heat dissipation and protect data.
  • 【What You Get】 - 1 x Portable Hard Drive, 1 x USB 3.0 Cable, 1 x User Manual, Gift-type shell packaging ,Three-year manufacturer's warranty and free technical support services.
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 you need a server-generated screenshot rather than a DOM canvas, ScreenshotNeo accepts one GET request and returns PNG, JPEG, WebP, or a PDF. It removes cookie-consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.

See the ScreenshotNeo API documentation for all options. A direct cURL request is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The same request in 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)

And in 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(`Screenshot failed: ${res.status}`);
const data = Buffer.from(await res.arrayBuffer());
require('node:fs').writeFileSync('shot.webp', data);

Every feature is included on every plan. The Free plan provides 1,000 shots per month with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free. Create a free ScreenshotNeo account to start with 1,000 screenshots a month and no card.

Which storage method should you use?

Need Recommended approach
One normal-sized local download toDataURL('image/png') plus an anchor with download.
Large image or repeated captures toBlob(), an object URL, and explicit URL revocation.
Later retrieval, sharing, or processing Upload the Blob to your own server or storage architecture.
Cross-origin pages, PDFs, or automated jobs Use a browser-based screenshot service such as ScreenshotNeo instead of relying on a client canvas.

The key distinction is that html2canvas creates the canvas; your export choice determines whether that canvas becomes a local file, a binary upload, or neither.

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

Frequently Asked Questions

Is a canvas data URL already stored as a file?

No. It is an encoded string held in memory. The browser creates a local file only when you place it on a downloadable link and trigger the download, or when your application sends the data to storage.

Can I reuse one Blob for both download and upload?

Yes. A Blob is a binary representation of the encoded canvas image, so application code can pass the same Blob to an object URL for download and to a multipart request, provided it has not discarded the reference.

Why does an iframe from another site disappear even when the rest of the page captures correctly?

A cross-origin iframe is not readable through its contentDocument. html2canvas cannot reconstruct that foreign document from the parent page; it must be rendered within its own origin or captured separately.

Quick Recap

SaleBestseller No. 1
Seagate 2TB Portable Hard Drive | USB 3.0 (STGX2000400)
Seagate 2TB Portable Hard Drive | USB 3.0 (STGX2000400)
This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable; The available storage capacity may vary.
$129.99
Bestseller No. 2
Seagate Portable 1TB External Hard Drive HDD – USB 3.0 for PC, Mac, PlayStation, & Xbox, 1-Year Rescue Service (STGX1000400) , Black
Seagate Portable 1TB External Hard Drive HDD – USB 3.0 for PC, Mac, PlayStation, & Xbox, 1-Year Rescue Service (STGX1000400) , Black
This USB drive provides plug and play simplicity with the included 18 inch USB 3.0 cable; The available storage capacity may vary.
$119.80
SaleBestseller No. 3

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.

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