What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Remove unwanted page content with an awaited page.evaluate() call, then capture only after the DOM mutation completes. Use a guarded querySelector() for an optional element, querySelectorAll() when every match must disappear, and page.screenshot() or page.pdf() for the output. If the element is rendered asynchronously, wait for an application-specific condition before removing it.
The reliable Puppeteer sequence
The order matters because screenshots and PDFs capture the page state that exists when the capture method runs. Navigate, wait for the content your capture depends on, remove the node in the page context, await that operation, and only then capture.
- Open the target URL with
page.goto(). - Wait for a meaningful readiness condition, such as a selector or application state.
- Run and await
page.evaluate()to mutate the DOM. - Call
page.screenshot()for an image orpage.pdf()for a PDF.
Remove one optional match
await page.evaluate(() => {
document.querySelector('.cookie-banner')?.remove();
});
await page.screenshot({ path: 'page.png', fullPage: true });
The optional-chaining operator makes a missing banner a no-op. Because the evaluation is awaited, Puppeteer does not proceed to the screenshot until the callback has finished.
Remove every matching node
await page.evaluate(() => {
document.querySelectorAll('.cookie-banner')
.forEach(element => element.remove());
});
await page.pdf({ path: 'page.pdf', printBackground: true });
Use this form when a site can insert several copies, such as a desktop banner plus a mobile variant. A selector that is too broad can remove legitimate content, so inspect the DOM and target the component class or ID rather than a generic element name.
Complete runnable script
This CommonJS example launches Chromium, waits for the page, removes an optional banner, and writes a full-page PNG. Install Puppeteer with npm install puppeteer; its package downloads a compatible browser during installation unless you configure it to use an existing browser.
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 60000
});
await page.evaluate(() => {
document.querySelector('.cookie-banner')?.remove();
});
await page.screenshot({
path: 'example.png',
fullPage: true
});
} finally {
await browser.close();
}
})();
networkidle2 is a useful general wait, but it is not proof that a single-page application has finished rendering. Prefer a state that matters to your page when one is available.
When the element appears after rendering
Client-side applications may add a banner only after JavaScript runs. In that case, wait for the relevant predicate rather than guessing with a fixed delay. Puppeteer’s waitForFunction() resolves when its page-context predicate becomes truthy and accepts timeout options.
await page.waitForFunction(
() => document.querySelector('.cookie-banner'),
{ timeout: 10000 }
);
await page.evaluate(() => {
document.querySelector('.cookie-banner')?.remove();
});
await page.screenshot({ path: 'clean.png', fullPage: true });
If the element may legitimately never appear, wait for the application’s “content ready” condition instead, then use the optional match:
#1 Best Overall
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
await page.waitForFunction(
() => document.querySelector('[data-page-ready="true"]'),
{ timeout: 15000 }
);
await page.evaluate(() => {
document.querySelector('.cookie-banner')?.remove();
});
This avoids failing a capture merely because an optional consent component was absent.
Choosing selectors and handling failures
querySelector() versus querySelectorAll()
querySelector() returns the first match. Use it when the page has one known component or when removing only the first match is intentional. querySelectorAll() returns all matches, allowing you to remove each one with forEach().
Guarded evaluation versus $eval()
A guarded DOM query is appropriate when absence is expected:
await page.evaluate(() => {
document.querySelector('#promo')?.remove();
});
page.$eval() is useful when a match is required, but it throws if no element matches. That failure is valuable when the page contract says the element must exist:
Rank #2
- 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
await page.$eval('#required-panel', element => element.remove());
Catch or report that exception deliberately rather than silently treating a missing required element as success. Puppeteer also provides $$eval() for applying a callback to every matching node.
Capturing an image or a PDF
Full-page screenshot
await page.screenshot({
path: 'page.png',
fullPage: true
});
Use fullPage: true when the output should include content below the viewport. For a viewport-only image, omit that option.
Element screenshot
To capture a remaining component, obtain an element handle and call its screenshot method:
const card = await page.$('.article-card');
if (!card) throw new Error('article card not found');
await card.screenshot({ path: 'card.png' });
Puppeteer scrolls the element into view when needed. An element handle becomes invalid if your removal step detaches that element; taking an element screenshot with a detached handle throws. Query the element again after any DOM mutation.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #3
PDF output and media type
Use page.pdf() for a PDF. Puppeteer generates PDFs with print CSS media by default:
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: { top: '16mm', right: '16mm', bottom: '16mm', left: '16mm' }
});
If the PDF should use the site’s screen styles, emulate screen media before removing and printing:
await page.emulateMediaType('screen');
await page.evaluate(() => {
document.querySelector('.cookie-banner')?.remove();
});
await page.pdf({ path: 'screen-styled.pdf', printBackground: true });
PDF options also include page dimensions or formats, margins, landscape orientation, page ranges, background graphics, and font readiness. Choose them according to the required document rather than assuming screenshot styling and print styling are identical.
CSS hiding versus DOM removal
Removing a node changes the document structure. If scripts depend on that node, removal can trigger errors or alter layout. A less invasive alternative is to hide it with a style rule:
Rank #4
await page.addStyleTag({
content: '.cookie-banner { display: none !important; }'
});
Use removal when the element must not occupy the DOM or affect scripts, and CSS hiding when preserving the node is safer. Whichever method you choose, apply it after the page has created the target and before capture.
Common mistakes and fixes
- Capture starts too soon: an unawaited
page.evaluate()or a promise chain that is not returned can let the screenshot run first. Prefix the mutation withawait. - Selector removes too much: narrow the selector and test it with
document.querySelectorAll()in DevTools before automating. - Missing optional element causes an exception: use optional chaining in
page.evaluate()instead of$eval(). - Required element silently disappears from the workflow: use
$eval()or an explicit count check and fail with a useful message. - Banner is added later: wait for a meaningful predicate with
waitForFunction(), or wait for your application’s ready marker. - PDF looks different from the page: remember that print media is the default; call
emulateMediaType('screen')when screen CSS is required. - Element screenshot reports a detached handle: query for a fresh handle after removing or replacing DOM nodes.
- Timeouts on pages with long-lived connections: use a selector or readiness predicate instead of relying only on network-idle events.
Performance, reliability, and operational notes
DOM removal itself is inexpensive; page loading, JavaScript execution, fonts, images, and PDF layout usually dominate capture time. Reuse a browser process for batches of pages, but create a fresh page per capture to isolate cookies, viewport settings, and mutations. Set explicit navigation and predicate timeouts so a stalled site cannot occupy a worker indefinitely, and always close pages and the browser in cleanup code.
For deterministic output, set the viewport and device scale factor before navigation, wait for fonts or application content that affects layout, and use stable selectors. If lazy-loaded images matter to a full-page capture, scroll or trigger the application’s loading mechanism before removing overlays. Record the URL, selector, wait condition, and output path with each job so a failed capture can be reproduced.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server. Its clean-shot workflow accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing result.
Free tools Windows power users keep installed
One-click scans. No signup required.
For a one-call image, see the ScreenshotNeo API documentation:
Best Value
- JavaScript Jquery
- Introduces core programming concepts in JavaScript and jQuery
- Uses clear descriptions, inspiring examples, and easy-to-follow diagrams
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 endpoint supports PNG, JPEG, WebP, or PDF and options such as full-page capture, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, custom CSS and JavaScript, clicks, wait conditions, blocked resources, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, cache TTLs, signed links, asynchronous jobs, webhooks, bulk capture of up to 100 URLs per call, usage data, and an OpenAPI specification. Its parameter names are compatible with those used by other screenshot APIs, easing migration.
ScreenshotNeo also includes an MCP server with take_screenshot, get_page_info, and capture_pdf tools 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. Sign up free.
FAQ
Can I remove an element without changing the source website?
Yes. page.evaluate() changes the loaded document in the browser context used for that capture; it does not edit the origin server’s files.
Should I remove a cookie banner or click its accept button?
Removing it is suitable when you only need a clean artifact. Click acceptance when the site must record consent or reveal content only after a consent action.
Why does a PDF contain a page element hidden in the screenshot?
Check whether your PDF uses print CSS, whether the selector matched the print version of the DOM, and whether a later script recreated the element before PDF generation.
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.




