Free tools Windows power users keep installed
One-click scans. No signup required.
Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use dom-to-image’s filter callback. The callback receives each descendant DOM node; return true to include it and false to omit it. Test node.classList for a class, compare node.id for an ID, or combine both tests. An excluded node takes its entire subtree out of the image.
How the dom-to-image filter works
dom-to-image does not document a selector-string option such as filter: '.ads'. Instead, pass a function in the rendering options object. The function is called with a DOM node and must return a Boolean:
true: include the node in the rendered output.false: exclude the node and all of its children.
The callback is not called for the root node supplied to the capture method. That exception matters when you are trying to remove the root itself: choose a parent as the capture root, or place the unwanted element below a wrapper that can be filtered.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Exclude a class
This filter removes every element carrying no-capture, while allowing text and other non-element nodes through:
#1 Best Overall
const root = document.getElementById('capture-root');
const filter = (node) =>
node.nodeType !== 1 || !node.classList.contains('no-capture');
domtoimage.toPng(root, { filter })
.then((dataUrl) => {
const image = new Image();
image.src = dataUrl;
document.body.appendChild(image);
})
.catch((error) => console.error('Capture failed:', error));
nodeType === 1 identifies an Element. The guard prevents errors if the library passes a text, comment, or other node that does not have classList. Returning true for non-elements is normally the least surprising behavior because the class rule cannot apply to them.
Class matching details
classList.contains()tests one complete class token, sono-capture-extradoes not accidentally matchno-capture.- Class names are case-sensitive in HTML and CSS matching.
- If a class is added or removed dynamically, run the capture after the DOM update has been applied.
- The rule applies to every matching descendant, not just the first one.
Exclude an ID
IDs should be unique, but comparing the string directly also works if a page contains duplicates:
const root = document.getElementById('capture-root');
const filter = (node) =>
node.nodeType !== 1 || node.id !== 'no-capture';
domtoimage.toPng(root, { filter })
.then((dataUrl) => {
const image = new Image();
image.src = dataUrl;
document.body.appendChild(image);
})
.catch((error) => console.error('Capture failed:', error));
An element with no ID has an empty id value and therefore passes this particular test. If your application assigns IDs at runtime, start the capture only after those assignments are complete.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesExclude by class, ID, or both
Either a class or a specific ID
Use a logical AND between the “not this class” and “not this ID” conditions. A node is included only when it satisfies both:
const filter = (node) => {
if (node.nodeType !== 1) return true;
const hasExcludedClass = node.classList.contains('exclude-from-capture');
const hasExcludedId = node.id === 'exclude-from-capture';
return !hasExcludedClass && !hasExcludedId;
};
domtoimage.toPng(document.getElementById('capture-root'), { filter })
.then((dataUrl) => {
const image = new Image();
image.src = dataUrl;
document.body.appendChild(image);
})
.catch((error) => console.error('Capture failed:', error));
Several classes or IDs
For a maintainable deny-list, use sets. This avoids a long chain of comparisons and makes the policy easy to change:
const excludedClasses = new Set(['ads', 'cookie-banner', 'chat-widget']);
const excludedIds = new Set(['debug-panel', 'print-controls']);
const filter = (node) => {
if (node.nodeType !== 1) return true;
const excludedByClass = [...node.classList]
.some((name) => excludedClasses.has(name));
const excludedById = excludedIds.has(node.id);
return !excludedByClass && !excludedById;
};
const root = document.querySelector('#capture-root');
domtoimage.toPng(root, { filter })
.then((dataUrl) => {
const link = document.createElement('a');
link.download = 'capture.png';
link.href = dataUrl;
link.click();
});
Choose the correct capture root
Because the callback is not invoked for the root passed to toPng, toJpeg, toBlob, toPixelData, or toSvg, filtering the root itself has no effect. For example, this will still render #capture-root:
const root = document.getElementById('capture-root');
const filter = (node) => node.id !== 'capture-root';
domtoimage.toPng(root, { filter });
To omit that region, capture an ancestor and filter the descendant:
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
const page = document.getElementById('page');
const filter = (node) =>
node.nodeType !== 1 || node.id !== 'capture-root';
domtoimage.toPng(page, { filter });
Remember that removing a node also removes its children. Conversely, filtering an ancestor cannot preserve a child inside it. Keep every ancestor needed to position the content you want to retain.
Use the filter with other output methods
The same options object is used with the library’s documented output methods. Replace only the method when you need another format:
const options = { filter };
const root = document.getElementById('capture-root');
const pngUrl = await domtoimage.toPng(root, options);
const jpegUrl = await domtoimage.toJpeg(root, options);
const blob = await domtoimage.toBlob(root, options);
const pixels = await domtoimage.toPixelData(root, options);
const svg = await domtoimage.toSvg(root, options);
These methods return promises, so handle success and failure with await/try…catch or .then()/.catch(). The README’s own filter example uses toSvg; the other methods are shown in separate examples but accept the rendering options pattern.
Common mistakes and fixes
Passing a selector string
Symptom: You write { filter: '.no-capture' }, but nothing is excluded or the library rejects the option.
Cause: The documented API expects a function, not a CSS selector string.
Fix: Test classList.contains() or id inside a callback as shown above.
Calling classList on every node
Symptom: An exception says classList is undefined.
Cause: The callback contract is node-based; not every DOM node is an element.
Rank #3
Fix: Guard with node.nodeType !== 1 before reading element properties.
The target is the root
Symptom: The element’s own ID or class is ignored.
Cause: The callback is not called for the capture root.
Fix: Capture an ancestor and filter the target as a descendant, or restructure the markup with a wrapper.
Children disappear unexpectedly
Symptom: Filtering a small-looking element removes more content than expected.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Cause: Excluding a node excludes its complete subtree.
Fix: Move the class or ID to the smallest wrapper that contains only the content you intend to omit.
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
Changes are not visible
Symptom: A newly applied class or removed ID has no effect.
Cause: Capture started before the DOM mutation, framework render, or style update completed.
Fix: Trigger the capture after the update (for example, in the framework’s post-render hook or a queued task).
Options copied from another package
Symptom: An option found in an online example is ignored.
Cause: dom-to-image-more and other forks document additional controls such as filterStyles. Fork documentation is not evidence that the original dom-to-image package supports those options.
Fix: Check the README and installed version for the exact package you imported, and keep the callback limited to documented behavior.
Recommended Free Tools
Performance and reliability considerations
Keep the predicate inexpensive: class and ID checks are constant-time operations for each visited element, while scanning large arrays or querying the document repeatedly can add unnecessary work. Pre-build sets outside the callback, as in the multi-rule example. Avoid modifying the DOM from inside the predicate; filtering should describe what to include, not mutate the tree being traversed.
Best Value
Use a stable capture root and wait until images, fonts, and application state are ready. If a capture fails, log the rejected promise so the underlying error is not hidden. Filtering cannot repair unrelated rendering problems such as inaccessible cross-origin resources, missing styles, or a root that is not present.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
For server-side or automated screenshots, ScreenshotNeo accepts one request and returns a PNG, JPEG, WebP, or PDF. It is not a DOM filter, so use the browser callback when you must remove a particular class or ID from an already rendered page. Use ScreenshotNeo when you want a remote capture without maintaining browser automation: it accepts cookie and consent banners before capture, removes more than 60 known consent platforms plus newsletter popups and chat widgets, and lets each cleanup step be disabled.
Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are reported in the response and cost nothing. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Outdated 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 matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallcURL
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(`HTTP ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
See the ScreenshotNeo documentation for parameters such as full-page capture, CSS selectors, custom JavaScript, waits, device presets, PDF settings, headers, cookies, geolocation, caching, signed links, asynchronous jobs, bulk capture, and usage reporting. The free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Can I filter the root node directly?
No. The documented callback is not called for the node passed as the capture root. Capture an ancestor if the root itself must be omitted.
Does excluding a parent preserve its children?
No. Returning false excludes the node and its entire descendant subtree.
Is filterStyles available in dom-to-image?
Do not assume so. That option is documented by the dom-to-image-more fork; verify the package and version installed in your project.
Frequently Asked Questions
Can I filter the root node directly?
No. The callback is not called for the node passed as the capture root. Capture an ancestor if the root itself must be omitted.
Does excluding a parent preserve its children?
No. Returning false excludes the node and its entire descendant subtree.
Is filterStyles available in dom-to-image?
Do not assume so. That option is documented by the dom-to-image-more fork; verify the package and version installed in your project.
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.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →

