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

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 Playwright when you need to change a page with JavaScript and then save the result. Call page.addScriptTag() after navigation for code that can run on an existing document. Use page.addInitScript() when your code must be installed after document creation but before the site’s own scripts execute. Once the page is ready, call page.screenshot() for a viewport or full-page image. This gives you control over timing, DOM changes, waiting, masking, output format and browser state.

This guide shows a complete Playwright workflow, explains Puppeteer, Chrome DevTools Protocol (CDP) and extension alternatives, and covers the failure modes that matter when a capture must be repeatable.

Choose the injection method first

The timing of your script determines what it can affect.

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

page.addScriptTag(): modify an already loaded page

addScriptTag() inserts JavaScript into the current page context. Use it after page.goto() when you want to change visible content, add a marker, click a control or adjust the DOM immediately before the capture. The script can be supplied as inline content or as a file path, as documented in the Playwright Page API.

#1 Best Overall
Sale
Philips 24 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 241V8LB
  • CRISP CLARITY: This 23.8″ Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors
  • WORK SEAMLESSLY: This sleek monitor is virtually bezel-free on three sides, so the screen looks even bigger for the viewer. This minimalistic design also allows for seamless multi-monitor setups that enhance your workflow and boost productivity
  • A BETTER READING EXPERIENCE: For busy office workers, EasyRead mode provides a more paper-like experience for when viewing lengthy documents

page.addInitScript(): run before site scripts

addInitScript() is evaluated after the document is created and before the page’s own scripts run. It is the right choice for early changes such as defining a value that application code reads during startup, replacing a browser API, or setting a flag before hydration. Playwright also evaluates an init script in newly attached or navigated child frames.

Neither method guarantees that a script can override every site. Content security policy, cross-origin frames, authentication, browser settings and application defenses can limit what is possible. Treat each target as a separate compatibility case.

Install Playwright and prepare a capture

  1. Create a project and install the library:

    npm init -y
    npm install playwright
    npx playwright install chromium
  2. Save your capture code in capture.js. The following example navigates, injects JavaScript, waits for a visible result and writes a full-page PNG.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage({
    viewport: { width: 1440, height: 900 },
    deviceScaleFactor: 1
  });

  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });

  await page.addScriptTag({
    content: `
      document.documentElement.dataset.captureReady = 'true';
      const banner = document.querySelector('[data-cookie-banner]');
      if (banner) banner.remove();
    `
  });

  await page.waitForSelector('[data-capture-ready], html[data-capture-ready="true"]', {
    state: 'attached',
    timeout: 10000
  }).catch(() => {});

  await page.screenshot({
    path: 'capture.png',
    fullPage: true,
    type: 'png'
  });

  await browser.close();
})();

Replace the URL and selectors with those used by your page. The example’s selector wait is intentionally defensive: a page may not contain a dedicated readiness element, so your production script should wait for a condition that actually represents finished rendering.

Inject code before navigation with an init script

Register the init script before calling goto(). This example sets a flag before application scripts run and applies it to every navigation in the page:

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  await page.addInitScript(() => {
    window.__captureMode = true;
    Object.defineProperty(navigator, 'language', {
      get: () => 'en-US'
    });
  });

  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  await page.screenshot({ path: 'init-script.png', fullPage: true });
  await browser.close();
})();

Use networkidle only when the page eventually becomes quiet. Analytics, polling and advertisements can keep a connection active indefinitely; in that case, prefer domcontentloaded followed by a selector or a bounded delay.

Rank #2
Philips 22 Inch Computer Monitor FHD 100Hz VA VESA Flicker-Free, 221V8LB
  • CRISP CLARITY: This 22 inch class (21.5″ viewable) Philips V line monitor delivers crisp Full HD 1920x1080 visuals. Enjoy movies, shows and videos with remarkable detail
  • 100HZ FAST REFRESH RATE: 100Hz brings your favorite movies and video games to life. Stream, binge, and play effortlessly
  • SMOOTH ACTION WITH ADAPTIVE-SYNC: Adaptive-Sync technology ensures fluid action sequences and rapid response time. Every frame will be rendered smoothly with crystal clarity and without stutter
  • INCREDIBLE CONTRAST: The VA panel produces brighter whites and deeper blacks. You get true-to-life images and more gradients with 16.7 million colors
  • THE PERFECT VIEW: The 178/178 degree extra wide viewing angle prevents the shifting of colors when viewed from an offset angle, so you always get consistent colors

Make the page capture-ready

Wait for a meaningful condition

Waiting for a selector is usually more reliable than sleeping for an arbitrary number of milliseconds:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.waitForSelector('.product-grid .product-card', {
  state: 'visible',
  timeout: 15000
});

For a known application state, wait for a function:

await page.waitForFunction(() => {
  return document.querySelectorAll('.chart svg').length > 0;
}, null, { timeout: 15000 });

Use a short, explicit delay only for animations or delayed fonts that have no observable readiness signal. Always keep a timeout so a broken page cannot stall a worker forever.

Handle lazy content

Full-page screenshots can trigger lazy loading, but a site may require scrolling to fetch images. Scroll in controlled increments, then wait for images:

await page.evaluate(async () => {
  await new Promise(resolve => {
    let y = 0;
    const step = 700;
    const timer = setInterval(() => {
      window.scrollBy(0, step);
      y += step;
      if (y >= document.body.scrollHeight) {
        clearInterval(timer);
        window.scrollTo(0, 0);
        resolve();
      }
    }, 100);
  });
});

await page.waitForFunction(() => {
  return [...document.images].every(img => img.complete);
}, null, { timeout: 20000 });

This is site-dependent: an image can be “complete” while its request failed, so inspect natural dimensions or application-specific loading markers when image integrity matters.

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

Control screenshot output

The Page API supports viewport or full-page captures, masks, temporary stylesheets, output formats and scaling options. Choose settings deliberately:

Rank #3
Sale
Dell 24 Monitor - SE2426H - 23.8-inch FHD (1920x1080) 144Hz 1ms Display, in-Plane Switching (IPS) Technology, AMD FreeSync™, TÜV 3-Star 2X HDMI, Tilt
  • Clear visuals. Fluid motion: A 144Hz refresh rate and 1ms MPRT deliver smooth, tear‑free motion across work, gaming, and streaming for clearer, more fluid viewing.
  • Eye comfort: TÜV Rheinland 3‑star* certification reduces harmful blue light while preserving stunning color quality without compromise. *TÜV Rheinland 3-star eye comfort certification.
  • Wide viewing angle: Get consistent views across a wide 178° /178° viewing angle.
  • In-Plane Switching (IPS): See excellent color accuracy and consistency across wide viewing angles with In-plane Switching (IPS) technology.
  • Ultra-thin bezels: Maximize your viewing experience with thin bezels.
  • Viewport versus full page: omit fullPage for the visible viewport; use fullPage: true for the page’s scrollable height.
  • Format: PNG preserves sharp text and transparency; JPEG is smaller but lossy; WebP can reduce size when your consumer supports it.
  • Scale: scale: 'css' keeps output close to CSS pixels, while scale: 'device' reflects device pixels. Set deviceScaleFactor on the context when you need retina-style output.
  • Mask sensitive regions: pass locators to mask and choose a maskColor so changing content does not appear in the artifact.
  • Temporary styles: style can hide a cursor, animation or nonessential widget for the capture without changing the site permanently.
await page.screenshot({
  path: 'controlled.webp',
  fullPage: true,
  type: 'webp',
  quality: 85,
  scale: 'css',
  mask: [page.locator('.live-chat'), page.locator('.personal-data')],
  maskColor: '#888888',
  style: `* { animation: none !important; transition: none !important; }`
});

Check the current option names and constraints in the Playwright Page API; supported combinations can vary by browser engine.

Run JavaScript in the right frame

page.evaluate(), addScriptTag() and selectors operate in the main frame unless you explicitly use a frame. If the target element is inside an iframe, locate that frame first:

const frame = page.frame({ url: /payments/ });
if (!frame) throw new Error('Payment frame not found');
await frame.addScriptTag({ content: 'document.body.dataset.capture = "ready";' });

Cross-origin restrictions still apply to what a frame can read. A script injected into the top page cannot freely inspect another origin’s DOM, and a frame may load after the initial navigation. Wait for the frame or its selector before injecting.

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

Alternative integration levels

Puppeteer

Puppeteer is a high-level JavaScript library for browser automation. Chrome for Developers describes it as automating Chrome and Firefox through Chrome DevTools Protocol and WebDriver BiDi, with workflows that include screenshots, PDFs, navigation and testing. Choose it when your team already uses Puppeteer’s API or its ecosystem. The same design concerns remain: inject at the correct time, wait for application readiness and bound every operation with a timeout.

Chrome DevTools Protocol

CDP is lower level. In the Page domain, Page.addScriptToEvaluateOnNewDocument installs code in frames as they are created, before their scripts load, while Page.captureScreenshot returns a screenshot. CDP is useful when you already manage a Chrome connection or need protocol commands unavailable in a wrapper, but you must handle sessions, targets, navigation events and binary output yourself.

Chrome extension scripting

For behavior owned by an extension, Chrome’s scripting API can inject JavaScript and CSS into websites. Its documented default timing is document_idle; if the page has already loaded, execution can occur immediately. An extension must have the required permissions and host access, and its injection scope differs from a standalone automation job.

Rank #4
Samsung 27" Essential S3 (S36GD) Series FHD 1800R Curved Computer Monitor
  • CURVED FOR ENHANCED ENGAGEMENT: An immersive viewing experience with a curved monitor that wraps more closely around your field of vision; It creates a wider view, enhancing depth perception and minimizing peripheral distraction
  • SMOOTH PERFORMANCE FOR SEAMLESS CONTENT: Stay in the action when playing games, watching videos, or working on creative projects; The 100Hz refresh rate reduces lag and motion blur so you don't miss a thing in fast-paced moments¹
  • MORE GAMING POWER: Gain the edge with optimizable game settings; Color and image contrast can be adjusted to see scenes more vividly and spot enemies hiding in the dark; Game Mode adjusts any game to fill the screen so you can view every detail²
  • KEEP IT EASY ON THE EYES: Care for your eyes and stay comfortable, even during long sessions; Advanced eye comfort technology certified by TÜV reduces eye strain by minimizing blue light and reducing irritating screen flicker²
  • INCREASED VERSATILITY: Connect to more; Plug devices straight into your monitor for increased flexibility, making your computing environment even more convenient

Comparison by integration and timing

Approach Integration layer Early-page option Best fit
Playwright High-level automation library addInitScript() Repeatable navigation, waiting and capture workflows
Puppeteer High-level automation library Early evaluation methods in its API Teams standardized on Puppeteer and Chrome automation
Chrome DevTools Protocol Browser protocol Page.addScriptToEvaluateOnNewDocument Direct control of an existing Chrome connection
Chrome scripting API Browser extension document_idle or immediate on loaded pages Features that must run inside an installed extension

No source establishes one universally superior method. Select based on whether you need a standalone worker, direct browser protocol access or extension-managed behavior.

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

Troubleshoot common capture failures

The injected code has no visible effect

  • Wrong timing: move startup logic from addScriptTag() to addInitScript(), or inject after the component has rendered.
  • Wrong frame: inspect page.frames() and inject through the matching frame.
  • Selector mismatch: verify the selector in the same browser state and wait for it before changing it.
  • Site protection: content security policy or application defenses may block or undo changes. Do not assume an injection can bypass them.

The screenshot is blank or incomplete

  • Wait for a real content selector rather than only navigation completion.
  • Confirm that the page did not redirect to an authentication or bot-check screen.
  • For lazy content, scroll and wait for image or component readiness.
  • Capture the viewport first to determine whether the issue is layout height, a failed resource or a full-page stitching edge case.

The script times out

Inspect which operation timed out: navigation, selector, function or screenshot. Reduce an overbroad networkidle wait, add a bounded fallback, and log the current URL and a small DOM marker before retrying. Reusing a single browser process while creating fresh contexts can reduce startup overhead, but close contexts and browsers on both success and failure.

Output differs between runs

Freeze animations with a temporary style, set a fixed viewport and device scale, choose a timezone and locale deliberately, wait for fonts and data, and mask timestamps or rotating ads. A screenshot tool cannot make inherently changing content deterministic without a page-specific strategy.

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

Or skip the browser setup

If you only need a rendered image or PDF, ScreenshotNeo provides a website screenshot API and MCP server. It accepts consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture; each cleanup step can be switched off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers report the page verdict and billing status.

One GET request returns PNG, JPEG, WebP or PDF. The API also supports custom JavaScript and CSS, clicking before capture, selector waits, delays or network-idle waits, element-only captures, full-page lazy-image loading, device presets, dark mode, retina scale, PDF page controls, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage data and an OpenAPI specification. Parameter names used by other screenshot APIs are accepted to ease migration.

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

Use the ScreenshotNeo documentation for authentication and option details. A minimal call is:

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 data = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', data);

Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients, so an AI agent can request captures without you building browser orchestration.

Best Value
Sale
Sceptre New 22-Inch Gaming Monitor, FHD 1080p, Up to 144Hz, HDMI, DisplayPort, Built-in Speakers, Machine Black (E225W-FW144 Series, 2026)
  • 【INTEGRATED SPEAKERS】Whether you're at work or in the midst of an intense gaming session, our built-in speakers provide rich and seamless audio, all while keeping your desk clutter-free.
  • 【EASY ON THE EYES】 Protect your eyes and enhance your comfort with Blue-Light Shift technology. This feature reduces harmful blue light emissions from your screen, helping to alleviate eye strain during long hours of use and promoting healthier viewing habits.
  • 【WIDEN YOUR PERSPECTIVE】Our sleek minimal bezel design ensures undivided attention. The nearly bezel-free display seamlessly connects in a dual monitor arrangement, delivering an unobstructed view that lets you focus on more at once, completely distraction-free.

Plans and a practical cost check

Plan Included shots Price
Free 1,000/month $0, no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Yearly billing gives two months free, and every feature is available on every plan. Create a free ScreenshotNeo account to get 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

Frequently Asked Questions

Can I inject JavaScript into a page after taking a screenshot?

No. The screenshot records the browser state at capture time. Inject the script, wait for its result, and then call the screenshot method.

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

Should I use Playwright or Puppeteer?

Both are high-level JavaScript automation libraries. Choose the one your project already supports; the decisive factors are injection timing, readiness waits and the browser state you need.

Will an init script modify every iframe?

Playwright documents init-script evaluation for newly attached or navigated child frames, but cross-origin access and site behavior can still limit what the script can read or change.

Can a screenshot API replace custom browser code?

For standard rendered captures, an API such as ScreenshotNeo can handle browser setup and offers custom JavaScript, waits and capture controls. Site-specific logic may still require your own Playwright workflow.

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.

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.