Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
browser automation

How to Modify the DOM With Puppeteer Before Taking a Screenshot

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

Use page.evaluate() after navigation and page-specific readiness checks, make the temporary DOM or CSS change inside the browser context, await the returned promise, and only then call page.screenshot(). The screenshot reflects the modified page; the site’s server and source files are not changed.

The reliable sequence

A screenshot is a rendering of the page state that exists when Chromium paints it. Puppeteer lets you change that state with page.evaluate(). The dependable order is:

  1. Launch Chromium and create a page.
  2. Set the viewport or device emulation that controls responsive layout.
  3. Navigate and wait for a useful baseline, such as networkidle2.
  4. Wait for the application-specific element or readiness signal your image needs.
  5. Run the DOM mutation in page.evaluate() and await it.
  6. Capture with page.screenshot() or an element handle’s screenshot method.
  7. Close the browser, or restore temporary changes if the page will be reused.

evaluate runs in the loaded page, not in Node.js. Browser APIs such as document, querySelector and getComputedStyle are available there. Values returned to Node.js must be serializable.

Complete runnable example

Install Puppeteer with npm install puppeteer, save this as modified-screenshot.mjs, and run it with Node.js. Replace the URL and selectors with those from your page.

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.
#1 Best Overall
Lavsoul 4K Webcam with Microphone for PC & Streaming Computer Camera
  • ULTRA HD 4K CLARITY: Stand out in every video call with breathtaking 4K video at 30fps or smooth 1080p at 60fps. Powered by a premium 1/2.5" CMOS sensor and a wide f/1.78 aperture, this webcam captures every detail with vibrant color and stunning low-light performance-so you always look your best
  • FAST AUTOFOCUS & SMART LIGHT CORRECTION: No more blurry moments with this webcam for PC. Advanced Phase Detection Auto Focus (PDAF) locks onto your face instantly and keeps you sharp-even when you move. Built-in light correction adapts to your environment, balancing brightness and contrast for a flawless image in dim rooms or bright spaces
  • DUAL NOISE-CANCELING MICS: Speak with confidence using this webcam with microphones. Dual microphones with intelligent noise-canceling tech isolate your voice and reduce background noise-suitable for webinars, live streams, team meetings, and virtual interviews
  • WIDE-ANGLE LENS & FLEXIBLE MOUNTING OPTIONS: Capture more of your world with an 80 field of view and full 360 swivel rotation. Whether this streaming webcam is mounted on a laptop, monitor, or tripod, it allows you to find the right angle for any setup
  • BUILT-IN PRIVACY COVER & PLUG-AND-PLAY SIMPLICITY: Protect your privacy with a secure sliding lens cover that blocks the camera when not in use. Setup is a breeze-just plug into any USB-A port and start streaming, chatting, or recording instantly. The USB webcam is compatible with Zoom, Microsoft Teams, Skype, OBS Studio, and all major platforms across Windows, macOS, and Linux
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();

await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.waitForSelector('body');

const result = await page.evaluate(() => {
  const banner = document.querySelector('.cookie-banner');
  banner?.remove();

  const title = document.querySelector('h1');
  if (title) {
    title.textContent = 'Screenshot title';
    title.style.color = 'rebeccapurple';
  }

  const style = document.createElement('style');
  style.dataset.screenshotOverride = 'true';
  style.textContent = `*, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }`;
  document.head.append(style);

  return {
    removedBanner: Boolean(banner),
    changedTitle: Boolean(title),
    injectedStyle: true
  };
});

console.log(result);
await page.screenshot({ path: 'modified.png', fullPage: true });
await browser.close();

The optional diagnostic object makes a failed selector visible in your logs instead of silently producing an unexpected image. The optional chaining operator prevents a missing banner from throwing an exception.

Choose the right DOM change

Remove a node

Call element.remove() when the element must disappear and its space should collapse. This is appropriate for consent banners, newsletter overlays and chat launchers that cover content.

await page.evaluate(() => {
  document.querySelector('.newsletter-modal')?.remove();
});

Hide without deleting

Use display: none when you want the element gone from layout but may need its DOM node later. Use visibility: hidden when the element must keep its layout space while becoming invisible.

Technique Layout space Use it when
remove() Collapses The node should not participate in layout or the DOM is disposable.
style.display = 'none' Collapses You may restore the node or inspect it before capture.
style.visibility = 'hidden' Preserved Alignment must remain unchanged while the pixels are hidden.
await page.evaluate(() => {
  const chat = document.querySelector('#chat-widget');
  if (chat) chat.style.display = 'none';

  const reserved = document.querySelector('.reserved-slot');
  if (reserved) reserved.style.visibility = 'hidden';
});

Change text safely

Assign textContent for plain text. It treats the replacement as text rather than parsing it as markup, so it is safer than innerHTML when you do not intentionally need HTML.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.evaluate(() => {
  const heading = document.querySelector('[data-screenshot-title]');
  if (heading) heading.textContent = 'Quarterly report';
});

Let the existing stylesheet do the work

Add a class when the page already defines the visual treatment you need. This avoids duplicating CSS in the script.

await page.evaluate(() => {
  document.querySelector('.product-card')?.classList.add('is-highlighted');
});

Inject temporary CSS

An appended <style> element is useful for screenshot-only rules: disabling motion, forcing a print-like color, or hiding a group of selectors. Give it a data attribute so it can be removed later.

await page.evaluate(() => {
  const style = document.createElement('style');
  style.dataset.captureOnly = 'true';
  style.textContent = '.ads, .chat-launcher { display: none !important; }';
  document.head.append(style);
});

If you reuse the same page, remove that style and restore inline properties after capture:

await page.evaluate(() => {
  document.querySelector('style[data-capture-only]')?.remove();
  const chat = document.querySelector('#chat-widget');
  if (chat) chat.style.display = '';
});

Wait for the state you actually need

waitUntil: 'networkidle2' is a useful navigation baseline, not a universal visual-ready signal. Fonts can load late, lazy images may not request data until scrolled into view, client-side data can arrive after navigation, and animations can keep changing pixels. Pages with analytics or other long-lived connections may never become meaningfully idle.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
10.1 Inch Mini Netbook, Quad-Core Processor Laptop Computer, 2GB Memory 64GB Storage Android 12 Portable Notebook Built-in Webcam, WiFi & Bluetooth Keyboard & Mouse for Home Schooling & Office Work
  • 【Efficient Quad-Core Performance】 Powered by a 1.8GHz Quad-Core processor, this mini laptop ensures smooth multitasking. With 2GB RAM and 64GB ROM (expandable to 1TB), it handles daily work and online tasks with ease.
  • 【10.1" HD IPS Display & GMS Support】 Featuring a 1280x800 HD IPS screen, this cheap laptop delivers vibrant visuals. Pre-installed with Android OS and GMS, you get direct access to the Google Play Store for apps.
  • 【Ultra-Portable & Lightweight Design】 Weighing only 1.76 lbs, this Blue computer is designed for mobility. Its compact form makes it an ideal companion for students and professionals for home schooling or trips.
  • 【Versatile Connectivity Options】 Stay productive with dual USB 2.0 ports, a headphone jack, and a TF card slot. This computer for kids and adults features built-in Wi-Fi and Bluetooth for stable connections.
  • 【Complete All-in-One Bundle】 This kid laptop kit includes the laptop, carrying bag, mouse, mouse pad, and power adapter. It is the perfect ready-to-use set for online classes, remote work, and entertainment.

Wait for a required element

await page.goto('https://example.com/dashboard', { waitUntil: 'domcontentloaded' });
await page.waitForSelector('[data-dashboard-ready]', { visible: true, timeout: 30000 });

Wait for an application flag

If your application exposes a readiness flag, wait for that condition rather than guessing with a fixed delay.

await page.waitForFunction(
  () => window.app?.state?.rendered === true,
  { timeout: 30000 }
);

Confirm images before capture

For pages whose image pixels matter, check completion in the page context after the relevant content has appeared.

await page.waitForFunction(() => {
  const images = [...document.images];
  return images.length > 0 && images.every(image => image.complete);
}, { timeout: 30000 });

Use a fixed delay only when the page supplies no observable signal. A delay can make a slow run pass while still failing on a slower run.

Set viewport and capture options deliberately

Set viewport and device emulation before navigation when responsive breakpoints affect the DOM or styling. Changing the viewport afterward can trigger a different layout from the one your mutation targeted.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.setViewport({
  width: 1280,
  height: 800,
  deviceScaleFactor: 2,
  isMobile: false,
  hasTouch: false
});

Choose the output scope and representation with screenshot options:

  • fullPage: true captures the document rather than only the visible viewport.
  • clip captures a rectangle with explicit x, y, width and height.
  • captureBeyondViewport controls captures that extend outside the current viewport.
  • path writes the file; type selects PNG, JPEG or WebP where supported.
  • encoding selects the returned representation when you request a buffer or base64 result.
  • quality affects encoders that support quality settings; PNG ignores it.
  • omitBackground: true keeps the page background transparent when the browser can represent it.
await page.screenshot({
  path: 'hero.webp',
  type: 'webp',
  quality: 82,
  fullPage: false,
  clip: { x: 80, y: 120, width: 1120, height: 520 }
});

Capture one element instead of the whole page

When the requirement is a component, find it after applying your mutation and use its element handle. Puppeteer can scroll a hidden element into view before taking the element screenshot.

Rank #3
Sale
Logitech C920x HD Pro Webcam, Full HD 1080p/30fps - Black w/Blue Yeti USB Microphone - Blackout
  • Webcam comes with a 3-month XSplit VCam license and no privacy shutter. XSplit VCam lets you remove, replace and blur your background without a Green Screen.
  • Full HD 1080p video calling and recording at 30 fps - You’ll make a strong impression when it counts with crisp, clearly detailed and vibrantly colored video.
  • Stereo audio with dual mics - Capture natural sound on calls and recorded videos.
  • Custom three-capsule array: This professional USB mic produces clear, powerful, broadcast-quality sound for YouTube videos, Twitch game streaming, podcasting, Zoom meetings, music recording and more
  • Blue VOICE software: Elevate your streamings and recordings with clear broadcast vocal sound and entertain your audience with enhanced effects, advanced modulation and HD audio samples
const card = await page.$('[data-testid="pricing-card"]');
if (!card) throw new Error('pricing card not found');
await card.screenshot({ path: 'pricing-card.png' });

For a stable clip that does not depend on a selector handle remaining valid, read the bounding box and pass it to clip:

const box = await page.locator('.invoice').boundingBox();
if (!box) throw new Error('invoice is not visible');
await page.screenshot({ path: 'invoice.png', clip: box });

Mutate, inspect, and capture complex pages

Use one evaluation for related changes

Grouping dependent edits in one function avoids capturing an intermediate state. Return counts or booleans that prove the selectors matched.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const audit = await page.evaluate(() => {
  const hidden = [...document.querySelectorAll('[data-hide-for-capture]')];
  hidden.forEach(node => { node.style.display = 'none'; });
  const selected = document.querySelector('.selected-row');
  selected?.classList.add('capture-focus');
  return { hiddenCount: hidden.length, focused: Boolean(selected) };
});
if (audit.hiddenCount === 0) console.warn('No capture-only elements matched');

Prevent moving pixels

Inject rules that disable transitions and animations immediately before capture. If a component uses a timer to replace its content, wait for its application signal as well; disabling CSS motion does not stop JavaScript from changing the DOM.

Handle lazy content

Full-page capture can require content that is below the fold. Trigger the page’s own loading behavior by scrolling, or wait for the specific lazy-loaded selector before the mutation. Do not assume that the first viewport contains every image needed in a full-page file.

Keep authentication and private data contained

Perform mutations in the already authenticated page context and write the resulting image to a controlled path. Avoid logging cookies, authorization headers or page text when returning diagnostics.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshooting

The screenshot still shows the element

  • Check the selector in DevTools or return a match count from evaluate.
  • Run the mutation after the code that inserts the banner; a late client-side render can recreate it.
  • Look for an iframe. A selector in the top document cannot directly select nodes inside a different frame; obtain the frame and evaluate there.
  • Check whether a later script restores the element. Capture immediately after the final mutation or observe the application state.

The page is blank or incomplete

  • Replace an early screenshot with a selector or application readiness wait.
  • Inspect navigation errors and console output.
  • Wait for image completion or the data request that populates the page.
  • Use a viewport and URL that reproduce the intended responsive route.

The layout jumps after hiding a node

You used a change that collapses layout space. Switch from remove() or display: none to visibility: hidden, or add a fixed placeholder with the dimensions the design requires.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #4
Webcam Cover for Logitech C920 C930e c922x Lens Privacy Shutter Slider
  • Compatible with Logitech C920x HD Pro Webcam, Full HD 1080p/30fps Video Calling. Compatible with Logitech C920 Hd Pro Webcam. Compatible with Logitech HD Pro Webcam C920 Widescreen Video Calling and Recording Webcam.
  • Compatible with Logitech C930e Webcam. Compatible with Logitech C922 Pro Stream Webcam 1080P Camera for HD Video Streaming. Compatible with Logitech Privacy Cover for C920 and C930e.
  • This webcam cover conveniently blocks your camera cover to protect your privacy.
  • This also compatible with other popular webcams. This is also known as webcam lid, webcam cap, webcam protector, web camera privacy cover.
  • ienza is a registered trademark and a registered Amazon brand. Use of the ienza trademark without the prior written consent of ienza, LLC. may constitute trademark infringement and unfair competition in violation of federal and state laws. ienza products are developed as cost-effective alternatives to OEM parts. They are not necessarily endorsed by the OEMs

Fonts or animations differ between runs

Wait for the page’s font-ready or application signal, then inject the temporary animation and transition override. A network-idle event alone does not establish that every visual dependency has settled.

evaluate throws an exception

  • Guard optional nodes with a null check or optional chaining.
  • Use browser-context globals only inside the evaluated function; Node variables must be passed as serializable arguments.
  • Make sure the function does not return a DOM node, element handle or other non-serializable object.

Performance, reliability, and repeatability

  • Reuse a browser process for a batch, but create an isolated page for each URL or tenant when state must not leak.
  • Set the viewport before navigation so the server-rendered and client-rendered layouts agree.
  • Prefer selectors and readiness flags over arbitrary sleeps; they finish quickly on fast runs and wait correctly on slow ones.
  • Keep mutations idempotent. A class can be added with a guard, and an injected style can be identified by a data attribute, so retries do not stack duplicate changes.
  • Record the URL, viewport, selector-match diagnostics and screenshot options with the output. This makes a visual difference explainable without storing sensitive page content.
  • Use PNG when lossless text and transparency matter; use JPEG or WebP when a smaller lossy file is acceptable. The encoder and chosen quality affect the result, and PNG does not use the quality setting.
  • Close pages and browsers in a finally path in production so a failed navigation does not leave Chromium processes running.

Or skip the browser setup

ScreenshotNeo provides a single screenshot API request when you do not need custom in-page JavaScript. It accepts the consent banner like a visitor, removes more than 60 known consent platforms, newsletter popups and chat widgets before capture, and lets you turn each cleanup step off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed as clean shots; the response identifies the result with X-Page-Verdict and X-Billed headers.

For a URL-only capture, use the documented endpoint and parameters:

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 request in 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)

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

See the ScreenshotNeo API documentation for options such as full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF output, custom CSS and JavaScript, click-before-capture, selector hiding, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting and the 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.

An MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 screenshots, and every feature is available on every plan. Create a free ScreenshotNeo account.

Frequently Asked Questions

Can I return a value from page.evaluate?

Yes. Return a plain serializable object, string, number or boolean and await the call in Node.js. Returning a DOM node or other browser-only object will not provide a usable Node.js value.

What is the safest way to make a temporary style identifiable?

Set a data attribute such as data-capture-only on the injected style element. You can then select that exact element and remove it before reusing the page.

When should I use an element screenshot rather than clip?

Use an element handle when the component is identified by a selector and should be scrolled into view automatically. Use clip when you already have stable document coordinates or need a precise rectangle.

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

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

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

Read next

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.