What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Remove only the canvas your application owns, then append the new one after html2canvas() resolves. The library returns a Promise for an HTMLCanvasElement; it does not decide where that node belongs in your page. Keep a reference to the previous output (or mark generated canvases), check that it is still connected, remove it, and insert the new canvas into a dedicated host. For fast, clean captures without browser setup, ScreenshotNeo can return an image or PDF from one request.
The reliable replacement pattern
A capture is asynchronous. The call to html2canvas(source) starts rendering and resolves later with a canvas. Your code is responsible for both insertion and cleanup. A minimal replacement function is:
const host = document.querySelector('#preview');
let previousCanvas = null;
async function replacePreview(source) {
const nextCanvas = await html2canvas(source);
if (previousCanvas?.isConnected) {
previousCanvas.remove();
}
host.append(nextCanvas);
previousCanvas = nextCanvas;
}
isConnected prevents errors when another part of the application has already removed the old node. The dedicated #preview host ensures that charts, signature pads, game canvases and other unrelated graphics remain untouched.
Replace a node in place
If the host contains exactly one generated canvas and you want the new image to occupy the same position, keep a stable wrapper and replace its child:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitches#1 Best Overall
async function replacePreview(source) {
const nextCanvas = await html2canvas(source);
const old = host.querySelector('canvas[data-html2canvas-output]');
nextCanvas.dataset.html2canvasOutput = 'true';
old?.replaceWith(nextCanvas);
if (!old) host.append(nextCanvas);
}
replaceWith() removes only the selected output. It does not affect siblings or canvases elsewhere on the page.
Prevent an older capture from winning
Two calls can overlap when a user changes a form quickly or clicks “refresh” repeatedly. Because html2canvas documents a Promise result but not cancellation, an earlier render may finish after a newer request. Without protection, that stale result can overwrite the current preview.
Use a serial (latest-request-wins) guard
const host = document.querySelector('#preview');
let previousCanvas = null;
let renderSerial = 0;
async function replacePreview(source) {
const serial = ++renderSerial;
const nextCanvas = await html2canvas(source);
if (serial !== renderSerial) return; // a newer request already started
if (previousCanvas?.isConnected) previousCanvas.remove();
host.append(nextCanvas);
previousCanvas = nextCanvas;
}
The serial is incremented before each capture. A completion is accepted only if its number still matches the latest request. This avoids displaying stale content while allowing the browser to finish work that html2canvas has already started.
Serialize captures when every result matters
A queue is preferable when captures must be processed in order, such as generating a set of archival images:
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
let captureQueue = Promise.resolve();
function enqueueCapture(source) {
const job = captureQueue.then(() => html2canvas(source));
captureQueue = job.catch(() => {}); // keep the queue usable after an error
return job;
}
async function renderInOrder(source) {
const nextCanvas = await enqueueCapture(source);
const old = host.querySelector('canvas[data-html2canvas-output]');
nextCanvas.dataset.html2canvasOutput = 'true';
old?.replaceWith(nextCanvas);
if (!old) host.append(nextCanvas);
}
Choose one policy: latest-request-wins for interactive previews, or serialization when each capture is required. Do not combine both without deciding which result should be visible.
Use a marker instead of a JavaScript reference
A reference is simplest while one component owns the output. A marker is useful when a component can be mounted again, when state is reconstructed, or when several independent previews share a host.
async function replaceMarkedPreview(source, host) {
const old = host.querySelector('canvas[data-html2canvas-output]');
old?.remove();
const next = await html2canvas(source);
next.dataset.html2canvasOutput = 'true';
host.append(next);
}
Scope the query to the component’s host. A document-wide selector can delete visualizations that your feature does not own. If multiple outputs are intentional, give each host a distinct identifier or add a key such as data-preview-id.
Reuse an existing canvas when node identity matters
The configuration includes a canvas option: an existing canvas element can be supplied as the drawing base. This keeps the same DOM node, which is useful when other code holds a reference, when layout observers are attached, or when a framework expects stable identity.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Rank #3
const canvas = document.querySelector('#previewCanvas');
await html2canvas(source, { canvas });
With this approach there is no old output node to remove; html2canvas draws into the supplied element. You still control when the canvas is shown and how it is sized. Do not pass a canvas that another feature is drawing into unless sharing that bitmap is deliberate.
What removeContainer actually removes
removeContainer defaults to true. It cleans the temporary cloned DOM that html2canvas creates while rendering. That cleanup container is an internal implementation detail. It is not the canvas your code appended to document.body or to #preview.
const output = await html2canvas(source, {
removeContainer: true
});
host.append(output); // this node remains until your code removes or replaces it
Setting or relying on removeContainer therefore does not solve “new canvas every time.” Remove the previous output yourself, or reuse an application-owned canvas with the canvas option.
Keep cleanup narrowly scoped
- Best: append outputs to a dedicated element such as
<div id="preview">and remove only its generated canvas. - Also safe: mark outputs with
data-html2canvas-outputor a class such ashtml2canvas-output, then query inside the owning component. - Avoid:
document.querySelectorAll('canvas')followed by removing every result. That can destroy charts, games, signature controls and other application state.
If a preview is unmounted, remove its host or its marked canvas in the component’s teardown. A disconnected reference can remain in JavaScript memory until released, so set previousCanvas = null when the owner is destroyed.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchRank #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
Rendering and bitmap-readability caveats
html2canvas reconstructs a page from the DOM and styles in the browser; it is not a pixel-perfect native screenshot engine. Unsupported CSS, fonts that have not loaded, animations and dynamic content can make the result differ from what a user sees.
Cross-origin images and tainted canvases
An image loaded from another origin can taint the bitmap. The canvas may display correctly but throw a security error when code tries to call toDataURL(), toBlob() or read pixels. The documented controls are:
useCORS: truewhen the image server sends an appropriate CORS header.proxywhen your server provides a same-origin proxy for remote assets.allowTaint: truewhen you accept a tainted canvas and do not need to read or export its pixels.
const output = await html2canvas(source, {
useCORS: true,
// proxy: '/image-proxy',
allowTaint: false
});
These options do not repair missing CORS headers. Fix the asset server or proxy configuration, then capture again.
Wait for content before capturing
Call the function after the source is visible and its images and fonts have loaded. For a user-triggered button, this usually means the page is already rendered. For programmatic startup, wait for document.fonts.ready and relevant image promises before invoking html2canvas.
Best Value
Common failures and precise fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| A new canvas appears on every click | The returned canvas is appended without removing the previous output. | Keep a reference or marker and call remove()/replaceWith() in the dedicated host before appending. |
| Charts or signature pads disappear | Cleanup uses a broad selector such as querySelectorAll('canvas'). |
Scope the selector to the preview host or a generated-output marker. |
removeContainer seems ineffective |
It removes temporary clones, not your appended result canvas. | Perform application-level output cleanup or pass an existing canvas. |
| An older image replaces newer content | Overlapping asynchronous captures complete out of order. | Use a serial guard for latest-request-wins or queue captures for strict ordering. |
toDataURL() or toBlob() throws a security error |
A cross-origin image tainted the canvas. | Use CORS-enabled assets with useCORS, a proxy, or avoid reading the bitmap with allowTaint. |
| The output is blank or incomplete | Capture ran before content, fonts or images were ready, or the page uses unsupported styling. | Wait for resources, make dynamic state deterministic, and treat html2canvas as DOM reconstruction rather than a native screenshot. |
Performance and lifecycle decisions
- Do not capture on every keystroke unless necessary. Debounce input and use the serial guard so work from superseded requests is ignored.
- Reuse a canvas when stable node identity and fewer DOM mutations matter; replace nodes when a simple immutable preview is easier to reason about.
- Keep the host mounted while a capture is running. If it is removed, check
isConnectedbefore cleanup and decide whether to discard the result. - Release discarded results by not appending stale canvases and by dropping references after a component unmounts.
- Measure memory for large pages. A high-resolution canvas consumes more memory than its CSS dimensions suggest, especially when device-pixel scaling is involved.
Or skip the browser setup
When you need a URL screenshot rather than a canvas reconstructed inside your page, ScreenshotNeo provides an HTTP screenshot API and an MCP server for AI agents. It accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and bills only clean shots: 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 request returns a PNG, JPEG, WebP or PDF. The API supports full-page captures with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper settings, custom CSS and JavaScript, clicks, waits, blocking rules, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Its parameter names are compatible with those used by many screenshot APIs.
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 API documentation for authentication, output controls and response headers. The MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it.
Choosing between replacement, reuse and an API
| Need | Best fit | Reason |
|---|---|---|
| Interactive preview inside the current page | Reference or marker replacement | You control exactly which output node is removed and displayed. |
| Stable DOM identity for other code | Existing canvas option |
html2canvas draws into an application-owned node. |
| Several rapid requests where only the newest matters | Serial guard | Stale Promise completions cannot overwrite current content. |
| Ordered archival captures | Serialized queue | Each render completes in the requested sequence. |
| Server-side URL images, PDFs or AI-agent workflows | ScreenshotNeo | Clean shots, only clean shots billed, and a $5 paid entry plan. |
FAQ
Can I remove the previous canvas before starting the next capture?
Yes, if a temporary blank preview is acceptable. Otherwise capture first and replace only after the Promise resolves, so the current image remains visible during rendering.
How can I tell whether a canvas is still in the document?
Use the DOM property canvas.isConnected. It is true when the node is connected to a document and false after removal or before insertion.
Does supplying canvas clear its old pixels automatically?
The option designates an existing canvas as the drawing base; if stale pixels matter, clear or size the canvas according to your rendering flow before reuse.
Why does a screenshot differ from the browser’s native screenshot?
html2canvas rebuilds the scene from accessible DOM and styles, so unsupported CSS, resource timing and cross-origin restrictions can produce differences even when replacement logic is correct.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →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.

