Most often, this error means html2canvas received no DOM element. In the matching historical report, the selected value was empty, so html2canvas eventually tried to call getElementsByTagName('img') on a value that was not an element. Check the complete stack trace, verify the selector result, and inspect the value immediately to the left of the failing method call before changing library code.
What the error actually tells you
Uncaught TypeError: undefined is not a function is not a diagnosis. It describes an attempted call through a value that is missing, has the wrong type, or does not expose the method being called. JavaScript produces undefined when you read an unassigned variable, when a function returns no value, or when you access a property that does not exist. The exact wording also varies by browser and context; Safari, for example, has used this wording for a non-iterable value in an iterable operation.
That is why the stack trace matters more than the text of the exception. Find the first line belonging to your application or the library call you made, then identify the exact expression that failed. The historical html2canvas case is specifically an element-selection problem, but the same message can originate in your callback, a later canvas operation, or unrelated application code.
Fix the selector before debugging html2canvas
1. Read the complete stack trace
Open your browser’s developer tools, reproduce the failure, and expand the exception. Locate the first useful application line and note the receiver of the failing call—the value immediately before the dot. For example, in target.getElementsByTagName('img'), the receiver is target. That is the value you must inspect.
#1 Best Overall
2. Prove that the target exists
A selector such as document.querySelector('#gridBody') returns null when no matching element exists. A misspelled ID, a script that runs before the markup is parsed, a component that has not rendered yet, or a selector scoped to the wrong document can all produce this result. Log the value and its type immediately before calling html2canvas:
const target = document.querySelector('#capture');
console.log({ target, type: typeof target });
if (!target) {
throw new Error('Capture target was not found');
}
if (!(target instanceof Element)) {
throw new TypeError('Capture target is not a DOM Element');
}
Use the selector that actually appears in your page. If the result is null, fix the selector or timing; do not try to patch html2canvas.
3. Run after the DOM is ready
If the script is in the document head or loaded before a component renders, the selector can be valid but still find nothing. Put the code after the target markup, use a deferred script, or wait for the application’s render event. A simple DOM-ready wrapper is:
document.addEventListener('DOMContentLoaded', () => {
const target = document.querySelector('#capture');
if (!target) throw new Error('Capture target was not found');
// Call html2canvas here, after the element exists.
});
For a framework-rendered element, query it only after the framework has mounted it. If the target is created asynchronously, wait for the specific condition rather than adding an arbitrary delay.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
A safe diagnostic call
Once the target check succeeds, isolate the html2canvas call and handle its result according to the API of the version installed in your project:
const target = document.querySelector('#capture');
if (!target) {
throw new Error('Capture target was not found');
}
html2canvas(target).then((canvas) => {
document.body.appendChild(canvas);
}).catch((error) => {
console.error('html2canvas failed:', error);
});
This Promise-style example is a diagnostic pattern, not a guarantee that every historical html2canvas release uses the same API. Verify the package version and its matching documentation before copying callback or option syntax from an old example. The matching Stack Overflow question dates from 2014, so its calling convention should not automatically be treated as current.
Inspect the failing receiver, not just your selector
If the selector returns an element and the exception remains, move to the exact failing expression. Check each value in the chain:
console.log('target:', target);
console.log('method:', target && target.getElementsByTagName);
if (!target || typeof target.getElementsByTagName !== 'function') {
throw new TypeError('The receiver does not provide getElementsByTagName');
}
An absent property evaluates to undefined. Calling it produces a TypeError, even when a variable elsewhere in the program is perfectly valid. Break long expressions into named variables so you can identify the first unexpected value.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #3
- Wrong selector result:
null, a collection, or a plain object was passed instead of one element. - Wrong document: the element is inside an iframe or shadow root, but the query ran against the top-level document.
- Timing problem: the element is inserted after the query.
- Callback problem: a function that should return an element returns nothing, so its caller receives
undefined. - Different failing operation: the error occurs after capture during image export, canvas manipulation, or application code.
Common selector mistakes and precise fixes
ID and class mismatches
#capture matches an element whose ID is exactly capture; it does not match a class or a differently capitalized ID. Confirm the markup in the Elements panel and test the selector directly in the console:
document.querySelector('#capture')
document.querySelectorAll('.capture').length
If several elements match, decide which one should be captured and select it deliberately. Passing a NodeList or HTMLCollection where one element is expected can trigger a later method failure.
Script runs before rendering
Move the script below the target, add defer to an external script, or invoke the capture from a user action that occurs after rendering. In a single-page application, inspect the element immediately before capture rather than at module initialization.
Iframe and shadow-root targets
A top-level document.querySelector cannot see into an iframe’s document, and ordinary selectors do not cross a shadow boundary. Obtain the correct browsing context or shadow root first, then query inside it. Also account for same-origin restrictions when accessing an iframe document.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Rank #4
- 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
Hidden or replaced nodes
A framework may replace a node after you store a reference to it. Re-query immediately before capture, and ensure the element is attached to the document. “Found” and “visible in the final layout” are separate checks; a detached or not-yet-laid-out node can create a different capture failure even when it is non-null.
When the error is not the selector
Use the stack location to classify the failure:
| Where the first failing line appears | What to check |
|---|---|
| Your selector or setup code | Selector spelling, return value, DOM timing, iframe or shadow-root scope. |
| Inside a callback | Whether every branch returns the value the caller expects; an omitted return yields undefined. |
| After html2canvas resolves | Whether the canvas, context, image, or export method exists before it is called. |
| Inside library code | Installed html2canvas version, browser/runtime, supported options, and the exact input passed to the library. |
Do not infer a universal html2canvas bug from one stack trace. Record the browser, full error, installed package version, target markup, selector, and the smallest code sample that still fails.
Version and compatibility checks
- Identify the installed version from your package lockfile or package manager.
- Read the API documentation that corresponds to that version.
- Check whether your example uses a callback, Promise, option name, or import style from an older release.
- Reproduce with the smallest page possible, using a known element such as
document.bodyonly as a control—not as proof that your real selector is correct.
The historical report notes that the same call worked with document.body. That comparison is useful: it suggests the library call itself can run, while the custom target may be empty or of the wrong type. It does not prove that every modern version has identical behavior.
Reliability and performance checks after the exception is fixed
- Capture only the element you need instead of an unnecessarily large document.
- Wait until images and fonts required for the target have loaded; otherwise a successful canvas can still be visually incomplete.
- Expect cross-origin image restrictions to affect rendering separately from selector errors.
- Release temporary canvases and avoid starting many captures at once on long pages.
- Keep error logging around both the target lookup and the capture Promise so future regressions identify the failing stage.
These are separate concerns from “undefined is not a function.” Fix the type and timing error first, then investigate blank images, missing assets, memory use, or cross-origin behavior with their own evidence.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsBest Value
Or skip the browser setup
If your goal is simply to obtain a dependable website screenshot rather than debug a browser canvas, ScreenshotNeo provides a single-request screenshot API. 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 identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for 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)
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 parameters and response handling. 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.
Quick troubleshooting checklist
- Read the first meaningful application or library line in the stack trace.
- Log the selector result immediately before capture.
- Reject
null,undefined, collections, and plain objects. - Confirm the query runs after rendering and in the correct document or shadow root.
- Inspect the method immediately before the failing call.
- Separate selector errors from callback, canvas, export, and cross-origin errors.
- Verify the installed html2canvas version before adopting an old snippet.
Frequently Asked Questions
Why does passing document.body work while my element fails?
That contrast usually means the custom lookup returned no usable element or returned a different type. Log the custom selector result and check its scope and timing.
Is this always an html2canvas bug?
No. The message can be raised by application code, a callback, a later canvas operation, or library code. The stack trace identifies which layer failed.
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 →Can I fix it by adding a delay?
Only if the element is genuinely created asynchronously. Prefer waiting for the render condition or event; an arbitrary delay can hide a race and remain unreliable.
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.

