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

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Use one Playwright browser, a context with fixed capture settings, and a loop that visits each approved URL and saves a uniquely named image. The example below captures full pages sequentially, records redirects and HTTP status, and continues after an individual failure. Before running it, check the access rules for every target site: no particular Indian government domain was assessed here, so permission, terms, robot rules, and request limits are not established.

Before you run a batch against government websites

Confirm that your intended collection complies with each target site’s terms, access controls, robots policy, and any applicable request limits. A publicly reachable URL is not, by itself, evidence that automated batch capture is permitted. Start with a small number of pages and avoid sending bursts of requests. The appropriate rate depends on the specific site; there is no universal safe concurrency or request-rate figure established for Indian government domains.

Playwright screenshots record the page appearance rendered by your browser setup at a point in time. They do not establish that a page is accessible or conforms to the Guidelines for Indian Government Websites (GIGW). The official GIGW portal provides guidance and resources; its accessibility guidance calls for meaningful text equivalents for images and other non-text content, with evaluation involving manual checks and accessibility tools. A screenshot alone cannot verify those requirements.

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

Set up Playwright and prepare a URL list

The example uses Node.js with Playwright’s Chromium browser. Install the package and its browser before running the script:

npm install playwright
npx playwright install chromium

Save the following as batch-screenshots.mjs. Replace the sample URLs with pages you are allowed to capture. It creates an output directory, visits pages sequentially, and writes a JSON-lines manifest so each saved file can be traced to its source and result.

import { chromium } from 'playwright';
import { mkdir, appendFile } from 'node:fs/promises';
import path from 'node:path';

const urls = [
  'https://example.gov.in/',
  'https://example.gov.in/about',
];
const outputDir = path.resolve('screenshots');
const manifestPath = path.join(outputDir, 'manifest.jsonl');
const timeoutMs = 30_000;

await mkdir(outputDir, { recursive: true });
const browser = await chromium.launch();
const context = await browser.newContext({
  viewport: { width: 1440, height: 1000 },
  locale: 'en-IN',
});

try {
  for (const [index, url] of urls.entries()) {
    const filename = `${String(index + 1).padStart(3, '0')}.png`;
    const outputPath = path.join(outputDir, filename);
    const page = await context.newPage();
    const timestamp = new Date().toISOString();

    try {
      const response = await page.goto(url, {
        waitUntil: 'domcontentloaded',
        timeout: timeoutMs,
      });

      // Replace or supplement this with a site-specific readiness check
      // when the page renders important content after initial navigation.
      await page.screenshot({ path: outputPath, fullPage: true });

      const record = {
        timestamp,
        requestedUrl: url,
        finalUrl: page.url(),
        httpStatus: response?.status() ?? null,
        outcome: 'captured',
        outputPath,
      };
      console.log(record);
      await appendFile(manifestPath, `${JSON.stringify(record)}n`);
    } catch (error) {
      const record = {
        timestamp,
        requestedUrl: url,
        finalUrl: page.url(),
        outcome: 'failed',
        error: String(error),
        outputPath: null,
      };
      console.error(record);
      await appendFile(manifestPath, `${JSON.stringify(record)}n`);
    } finally {
      await page.close();
    }
  }
} finally {
  await context.close();
  await browser.close();
}

Run it with node batch-screenshots.mjs. The numbered filenames are unique within this run, so URL normalization collisions cannot overwrite another page. The manifest records the requested and final URLs, capture time, outcome, and output path for successful captures; failures are logged without stopping the rest of the batch.

Choose what each screenshot should show

Playwright’s screenshot guide and Page API document the capture modes and options. Choose the smallest scope that preserves the evidence you need.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Capture scope How to capture When it fits
Viewport await page.screenshot({ path: outputPath }); Use the visible browser area when you need a consistent, fixed-size view.
Full page await page.screenshot({ path: outputPath, fullPage: true }); Captures the full scrollable document as one image. Long pages can produce very tall files; the documentation does not set a universal size threshold.
One element await page.locator('main').screenshot({ path: outputPath }); Use a CSS selector for a component or content region rather than the entire page.
Fixed rectangle await page.screenshot({ path: outputPath, clip: { x: 0, y: 0, width: 800, height: 600 } }); Use clip when a particular page-coordinate region is the intended record.

For image output, Playwright supports PNG, JPEG, and WebP. JPEG and WebP can use a quality setting where supported; choose a format based on whether compact files or lossless detail matters. The scale option can use 'css' for one image pixel per CSS pixel or device scale for device-pixel sizing. Keep format, quality, viewport, and scale consistent when comparing captures.

Options for animations, caret visibility, masks, and injected styles can reduce known visual variation. Apply them deliberately: hiding or covering content may make an image unsuitable as a record of what visitors actually see.

Wait for the page content you need

page.goto() supports load, domcontentloaded, networkidle, and commit navigation conditions. The current Page API discourages treating networkidle as a general readiness test; it recommends assessing readiness with assertions. A navigation event means a browser lifecycle condition was reached, not necessarily that delayed or client-rendered content is ready for your screenshot.

For a known page element, wait for that locator after navigation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
await page.locator('main h1').waitFor({ state: 'visible', timeout: 10_000 });
await page.screenshot({ path: outputPath, fullPage: true });

Replace main h1 with a selector that signals the content your capture depends on. A fixed delay can be used when a site has a known delay, but it is less precise than waiting for a meaningful page condition. Record the readiness rule alongside your capture settings so later comparisons use the same criterion.

Keep output names and browser state under control

Sequential numbering in the example avoids collisions and retains input order. If you prefer filenames derived from URLs, sanitize characters that are invalid or awkward in filenames and include a stable index or hash: different URLs can normalize to the same name. Keep the manifest even when names are descriptive; redirects mean the final page URL may differ from the input.

The example uses one non-persistent browser context with a shared viewport and locale. A context can hold multiple pages and applies shared emulation settings. If pages must not share cookies or storage, create separate non-persistent contexts for the relevant targets rather than reusing one stateful session; Playwright documents these contexts as isolated sessions. Do not share state across sites unless that is appropriate for your capture purpose.

For responsive review, create separate runs or contexts for each deliberate viewport and record the dimensions with the output. Keep browser version, operating environment, headless mode, viewport, device scale, locale, and color scheme stable where practical. Playwright’s visual comparison guidance notes that rendering can vary with the operating system, browser version, settings, hardware, power source, and headless mode. Dynamic banners, dates, rotating content, animation, and personalization can also make two captures differ. A screenshot represents what that setup rendered, not a canonical image for every visitor’s device.

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.

Scale cautiously and handle failures per URL

Sequential capture is a straightforward starting point for modest lists: it avoids an unbounded burst of page navigations and makes failures easy to associate with their inputs. For larger lists, bounded concurrency can reduce total elapsed time, but also increases simultaneous browser resource use and requests to the target. Add it only after checking the policies of each target site and your own capacity. Playwright supports multiple pages in a context; that does not establish a safe request rate for any government website.

Keep explicit navigation and locator timeouts. The example catches errors for each URL, writes a failure record, closes that page, and continues. Review the manifest after each run rather than assuming every input produced a screenshot. An HTTP response status is recorded when available; a returned response does not, by itself, mean the page contains the intended content.

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

Troubleshoot common batch-capture problems

  • Navigation times out: The page may be slow, unavailable, or waiting on activity that your chosen condition does not resolve. Check the URL and target policy, inspect the page manually, and select a suitable navigation condition or locator-based readiness check. Increase the timeout only when the site and task justify it.
  • The image is blank or missing content: Initial navigation may complete before client-rendered content appears. Wait for a meaningful element or other site-specific condition after goto(), and verify the resulting page and final URL.
  • Some pages redirect: Compare requestedUrl with finalUrl in the manifest. Confirm that the redirect is expected and that the final destination is in scope before treating the image as the requested page.
  • A file is unexpectedly large or tall: Full-page capture includes the scrollable document. Use viewport or element capture if that is sufficient, or choose a suitable image format and quality; preserve enough detail for the intended use.
  • Repeated runs look different: Hold browser/runtime, viewport, device scale, locale, color scheme, and capture options steady. Check for dynamic content, animations, banners, and personalization before interpreting differences as page changes.
  • The script stops after one bad URL: Keep navigation and capture inside the per-URL try/catch and close each page in finally, as in the example. Errors outside that block, such as browser launch or output-directory failures, still stop the run and should be fixed before retrying.
  • Two derived filenames would collide: Use a unique sequence number or add a stable hash to sanitized URL-based names. Keep the requested URL in the manifest to preserve the mapping.

Or skip the browser setup

ScreenshotNeo offers a one-request screenshot API and an MCP server for AI agents. Its cleanup can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Those behaviors do not override a target site’s access rules: check them before submitting URLs.

One request returns an image or PDF; see the ScreenshotNeo API documentation for request options. Replace the URL below with a permitted target:

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.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.gov.in/ -o shot.webp

ScreenshotNeo has 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 without a card; paid plans start at $5 for 3,000 screenshots. Visit ScreenshotNeo for product details, or sign up free.

FAQ

How do I capture only the visible browser area?

Call page.screenshot({ path: outputPath }) without setting fullPage: true; the default capture is the viewport.

Can screenshots prove a government page is accessible?

No. They document rendered appearance. Accessibility evaluation also requires checks beyond a screenshot, including meaningful text alternatives for non-text content.

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.

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