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

Start with the stack trace, then verify the value you pass to html2canvas(). In the closely matching historical report, the failure occurred when html2canvas called getElementsByTagName('img') on a target that was not an element. The accepted diagnosis was an empty selector result. That is the best first check for this case, but the message alone is not a universal diagnosis: the same wording can arise from other missing properties, callbacks, canvas code, or browser-specific error reporting.

What the error actually means

JavaScript throws this kind of TypeError when code tries to call a method through a value that is not the expected object. For example, if target is undefined, then target.getElementsByTagName('img') cannot work. Reading a property that does not exist also produces undefined, as documented by MDN’s undefined reference.

Safari has also used “undefined is not a function” for a non-iterable value in an iterable operation. Therefore, read the complete stack and the exact expression before changing code. Do not assume every occurrence originates inside html2canvas.

Fix the selector first

If you select an element by ID, class, or another CSS selector, prove that the selector matched before invoking the library.

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.
const target = document.querySelector('#capture');

if (!target) {
  throw new Error('Capture target was not found');
}

html2canvas(target).then((canvas) => {
  document.body.appendChild(canvas);
});

Replace #capture with the selector used by your page. Check the spelling, capitalization, and whether the element is rendered at all. A selector that matches nothing returns null (or an equivalent empty result when using a different selection API), and passing that result onward causes a failure later.

Confirm the element in DevTools

  1. Open the page and press F12 (or use your browser’s Developer Tools command).
  2. In the Console, run document.querySelector('#capture').
  3. Confirm that the returned object is the intended DOM element, not null, a collection, or a wrapper object from another library.
  4. Run document.querySelector('#capture').getElementsByTagName and confirm that the result is a function.

If the first expression returns null, fix the selector or the markup before debugging html2canvas.

Make sure the code runs after the DOM exists

A correct selector still fails if the script executes before the element has been parsed. Put the script at the end of the document, use defer, or wait for DOMContentLoaded.

document.addEventListener('DOMContentLoaded', () => {
  const target = document.querySelector('#capture');
  if (!target) {
    console.error('No capture target in the current document');
    return;
  }

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

This Promise example is illustrative. Check the API documentation for the exact html2canvas version installed in your project before adopting callback or Promise syntax.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Inspect the receiver at the failing line

Find the first application or library line in the stack that identifies the failing call. Look immediately to the left of the dot:

  • target.getElementsByTagName(...): verify target.
  • options.onclone(...): verify that the callback exists and is a function.
  • canvas.toDataURL(...): verify that the preceding operation actually returned a canvas.
  • someObject.method(...): verify both someObject and method.

Log the value and its type immediately before the call:

console.log({ target, type: typeof target });
console.log('has getElementsByTagName:',
  !!target && typeof target.getElementsByTagName === 'function');

This distinguishes an empty selector from an unrelated undefined variable or a missing method.

Common target mistakes

Passing a selector string instead of an element

Most html2canvas usage expects a DOM element. Pass the result of querySelector, not the literal string:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
// Wrong for an element-based API:
html2canvas('#capture');

// Correct:
const target = document.querySelector('#capture');
if (target) html2canvas(target);

Using a collection as one element

querySelectorAll() returns a NodeList, even when it contains one item. Select an item explicitly or iterate:

const items = document.querySelectorAll('.card');
items.forEach((item) => html2canvas(item));

Capturing a component that has not mounted

Framework-rendered content may not exist during the first synchronous line of a component. Trigger capture from the framework’s mounted or rendered lifecycle, then perform the same null check. If the element is conditionally displayed, verify that the condition is true in the browser where the error occurs.

Replacing or removing the node

Single-page applications can replace a DOM node between selection and capture. Select as close as possible to the call, and do not retain a stale reference across a render.

Separate html2canvas errors from application errors

The stack trace can point to your selector, a callback, an image-loading operation, a canvas conversion, or library internals. Record:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
  • the complete message and stack;
  • the exact expression at the first relevant line;
  • browser and operating-system details;
  • the installed html2canvas version and package manager lockfile;
  • the input URL or route and whether the target is present there.

The matching public report dates from 2014. Its callback pattern and assumptions should not be copied as current instructions without checking the version in your project. The reviewed material does not establish a current version-specific API fix.

A reliable diagnostic sequence

  1. Read the entire stack. Locate the first line that identifies the failing call.
  2. Reproduce with a direct DOM query. Confirm that the selector returns the intended element in the failing route.
  3. Check the receiver. Log the value immediately left of the failing dot and test the method with typeof.
  4. Check timing. Move the call after DOM creation, component mounting, or the user action that reveals the target.
  5. Check the API shape. Ensure you pass an element rather than a string, collection, wrapper, or stale reference.
  6. Isolate callbacks and later operations. Temporarily remove custom hooks and canvas-export code to identify which stage throws.
  7. Verify the installed version. Read the documentation and type definitions that match your lockfile, not a decade-old snippet.

When a browser screenshot is the wrong layer

Html2canvas runs in the page and is useful when you need a client-side canvas. It also inherits browser timing, cross-origin image restrictions, consent banners, popups, chat widgets, and bot checks. If your goal is a server-side screenshot or PDF rather than a canvas inside the current page, an HTTP screenshot API avoids setting up a browser and DOM code.

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 is 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. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; each response reports the page verdict and billing status in X-Page-Verdict and X-Billed headers.

One GET request returns PNG, JPEG, WebP, or PDF. The same service supports full-page captures with lazy images loaded, CSS-element capture, dark mode, device presets, arbitrary viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, selector hiding, selector/delay/network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, selectable-TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs also work, which can simplify migration.

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

For AI workflows, its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

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(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

See the ScreenshotNeo documentation for options and response headers. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account to try it.

Troubleshooting by symptom

Symptom Likely cause Fix
Fails immediately on the html2canvas call Empty selector, wrong value type, or code ran too early Log the target, add a null check, and run after the element exists
Stack points to a custom callback Callback or callback receiver is undefined Check the callback’s type and its referenced variables
Capture succeeds but export fails Later canvas operation is the failing expression Inspect the returned canvas before calling conversion methods
Only one browser reports this wording Runtime-specific error text Use the stack and expression, not the wording alone
Old example works nowhere Version/API mismatch Check the installed package and matching documentation

What the original report can—and cannot—prove

The historical Stack Overflow case shows one concrete diagnosis: the selector supplied to html2canvas matched nothing, while document.body worked. It does not establish that every “undefined is not a function” report has that cause, nor does it provide a current success rate or a current html2canvas version remedy. Treat it as a useful first branch in the decision tree, then follow your own stack trace.

Frequently Asked Questions

Should I replace html2canvas because of this message?

Not based on the message alone. First identify the failing expression and verify the target value; replacement is unrelated if your application passed an empty or wrong object.

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

Why does document.body work while my selected element fails?

document.body is present when the document is active. Your selector may be misspelled, run before rendering, scoped to a different document, or matching no node.

Can this error be caused by a browser rather than my selector?

Yes. Error wording differs across runtimes, and Safari has used it in an iterable context. The stack trace determines which operation actually failed.

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.