ScreenshotNeo

BlogHow-to

How to Take a Playwright Screenshot of a Bank Website in India Without Exposing Account Details

Mask sensitive page regions, capture only what you need, and inspect the saved image before sharing a Playwright screenshot of a bank website.

By the ScreenshotNeo team4 October 20268 min read

Use Playwright’s screenshot mask option to cover known sensitive elements, or its capture-time style option to hide them. Keep the screenshot scope as small as possible: capture a specific element or clipped region when that is enough, and leave fullPage off unless you need the entire scrollable page. Then inspect the saved image before sharing it. Selectors vary by bank page, so there is no universal selector that safely hides every account detail.

Use an authorized, non-sensitive test context for a tutorial. Do not enter real credentials or OTPs just to create an image. The Reserve Bank of India advises customers never to share their internet banking ID, password, mobile banking PIN, or OTP, including with bank staff. See the RBI Financial Awareness Messages.

1. Set up a safe Playwright capture

The example below uses JavaScript with Playwright. The selectors are placeholders for elements you have identified on an authorized page; they are not verified selectors for any Indian bank. For a runnable demonstration, point the script at a synthetic test page that contains elements with the matching attributes.

import { chromium } from 'playwright';

const targetUrl = process.env.TARGET_URL;
if (!targetUrl) {
  throw new Error('Set TARGET_URL to an authorized test page.');
}

const browser = await chromium.launch({ headless: true });
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });

try {
  await page.goto(targetUrl, { waitUntil: 'domcontentloaded', timeout: 30_000 });

  // These data attributes are example selectors. Adapt them only after
  // inspecting the page DOM in an authorized, non-sensitive test context.
  const sensitive = [
    page.locator('[data-sensitive="account-number"]'),
    page.locator('[data-sensitive="balance"]'),
    page.locator('[data-sensitive="customer-name"]'),
  ];

  await page.screenshot({
    path: 'bank-page-redacted.png',
    fullPage: false,
    mask: sensitive,
    maskColor: '#222222',
    animations: 'disabled',
  });
} finally {
  await browser.close();
}

Install the package and browser once in your project with npm install -D playwright and npx playwright install chromium. Set TARGET_URL to a test page you control, then run the script with Node.js. The output is a PNG in the current directory.

Playwright covers matched locator bounding boxes with an overlay; the documented default mask color is pink (#FF00FF). Setting maskColor makes the redaction visually distinct from the page. A mask only covers matched elements, so missing or overly broad selectors can respectively expose details or obscure useful content. Consult the Playwright Page API documentation.

2. Identify sensitive regions without guessing

Account numbers are only one possible disclosure. Check for balances, customer names, transaction descriptions, account identifiers, contact details, and any information revealed after scrolling, expanding a section, or loading dynamic content. Use the DOM of the authorized page to identify the actual elements. Do not assume a class name or selector works across banks, pages, or redesigns.

  1. Navigate only to the bank’s verified official website when the task genuinely requires it. RBI advises using trusted browsers and HTTPS-secured websites for payments, and warns against entering credentials on untrusted portals.
  2. Prefer a synthetic or otherwise authorized test page for development and documentation. Do not share or place real credentials, PINs, or OTPs in screenshots, chat, issue trackers, or support requests.
  3. Inspect the page structure and select each private region you need to cover. Add separate locators for separate fields when that makes coverage easier to verify.
  4. Capture the image and review the actual file at normal viewing size, including edges and content that appears after scrolling or dynamic updates.

3. Choose a masking method

Locator masks for known elements

Use mask when you can identify specific elements. It places an overlay over each matched locator’s bounding box while capturing. This keeps the page layout visible while obscuring the selected regions. Make sure the mask covers all of each value, including any adjacent text that could identify the customer.

await page.screenshot({
  path: 'redacted.png',
  mask: [
    page.locator('.account-number'),
    page.locator('.account-balance'),
  ],
  maskColor: '#222222',
});

The class names above are examples only. Replace them with selectors verified against your page. If a locator matches multiple elements, check that every match is intended to be masked.

Capture-time stylesheet for categories of content

Use style when CSS selectors can hide one or more categories of content. Playwright applies the stylesheet while making the screenshot; its documentation says this style pierces Shadow DOM and inner frames.

await page.screenshot({
  path: 'redacted.png',
  style: `
    .account-number,
    .account-balance,
    .customer-name {
      visibility: hidden !important;
    }
  `,
});

These class names are placeholders too. Hiding content can leave blank space in the layout, while removing it can shift other content. Choose the visual result that serves the screenshot’s purpose, and inspect it. A stylesheet is only as complete as its selectors.

4. Limit what the screenshot includes

Use the narrowest capture scope that answers the question. Playwright supports element screenshots, a viewport screenshot by default, a clipped region, and fullPage capture of the full scrollable page.

Capture scope When to use it Privacy consideration
Locator screenshot One component or panel is all that is needed. Reduces unrelated page content in the image. Any sensitive content inside that element still needs review.
clip A specific rectangle is needed. Keep the rectangle tight and verify its edges do not include adjacent details.
Viewport (default) The visible screen area is sufficient. Review all visible regions and any overlays or sticky elements.
fullPage: true The full scrollable page is genuinely required. Can include below-the-fold information that was not visible in the initial viewport; inspect the entire output.
// Capture just one identified component
await page.locator('#summary-panel').screenshot({ path: 'summary.png' });

// Or capture a small region of the viewport
await page.screenshot({
  path: 'region.png',
  clip: { x: 120, y: 180, width: 720, height: 260 },
});

// Use fullPage only when the whole scrollable page is needed
await page.screenshot({ path: 'whole-page.png', fullPage: true });

Element-level capture and clipping reduce the amount of page content included; they do not automatically redact information within the chosen area. Apply masks or a stylesheet as needed, and review the saved image.

5. Make capture timing predictable

Bank pages and test pages can render content dynamically. If a sensitive region appears after initial navigation, capture only after the page reaches the state you intend to document. Wait for a known element in your authorized test context, or use an appropriate page readiness condition. Avoid adding real login credentials to automation just to reach a screenshot state.

await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
await page.locator('[data-test="summary-ready"]').waitFor({ state: 'visible' });
await page.screenshot({
  path: 'redacted.png',
  mask: [page.locator('[data-sensitive]')],
});

The readiness selector and sensitive selector are examples that should be provided by a page you control. A fixed delay can be used for known animation timing, but it is less reliable than waiting for a meaningful page condition.

6. Review before sharing

  • Open the saved image itself; do not rely only on the DOM or on the script completing successfully.
  • Check every sensitive value, including names, balances, transaction details, identifiers, and content near the crop edges.
  • Check the full image if fullPage was used, including lower sections and repeated account information.
  • Check dynamic states, expanded panels, sticky headers, and overlays that may have appeared during capture.
  • If any private detail is visible or you cannot confirm coverage, do not share the image. Adjust selectors or capture a smaller area and create a new image.

7. Common problems and fixes

Problem Likely cause Fix
Sensitive text remains visible The selector did not match the element, the value rendered later, or another copy appears elsewhere. Inspect the authorized page DOM, wait for the intended state, add locators for all occurrences, and review a fresh output image.
A mask covers too much or too little The locator’s bounding box differs from the visual region you intended to cover. Refine the locator to the right element or use a tightly scoped capture. Recheck the image edges.
Stylesheet has no visible effect The example selector is not present or does not target the rendered content. Verify the selector against the actual page structure. The sample class names are not universal.
Screenshot is missing content The page or a dynamic component was not ready at capture time. Wait for a meaningful readiness condition on an authorized test page before capturing.
Image includes unexpected lower-page details fullPage: true captured more scrollable content than needed. Use the default viewport, an element screenshot, or a smaller clip region.
Script cannot launch Chromium The Playwright browser binary has not been installed for the project. Run npx playwright install chromium in the project environment.
Navigation times out The destination is slow, unavailable, or does not reach the selected readiness state within the timeout. Use an authorized test target, choose a suitable navigation condition, and set a bounded timeout. Do not assume timeout means the page was safely captured.

8. Performance, reliability, and privacy notes

Viewport and element screenshots generally involve less page content than full-page captures. Full-page capture may require additional rendering and can expose information far below the initial view. Capture only what is needed, and avoid repeatedly loading a sensitive site during development.

Masking is a capture-time visual treatment, not a substitute for checking the output. Its reliability depends on selecting every sensitive element in the state being captured. A changing page, delayed content, or an unanticipated second copy can defeat an incomplete selector. For anything you plan to share, inspect the image file after capture.

RBI guidance says not to share banking IDs, passwords, mobile banking PINs, or OTPs. Do not include those secrets in screenshots or in automation scripts. This workflow is technical privacy guidance, not a determination of legal compliance for a particular bank or disclosure.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. The API can capture web pages, but do not submit account credentials or expose a private banking session to an external capture service. Use only a public, non-sensitive page that is appropriate to capture.

For a public page, this cURL example saves a WebP screenshot. See the ScreenshotNeo API documentation for request options and setup.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, failed loads, and cache hits are never billed. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 shots.

Sign up for 1,000 free screenshots a month, with no card required.

FAQ

Can I use one selector that works for every Indian bank?

No. The page structure and rendered content vary. Identify selectors for the specific authorized page and check the resulting image.

Does a mask delete the underlying data from the page?

No. The screenshot mask covers the matched region in the captured image. Avoid sharing the image if any sensitive content remains visible, and do not treat masking as permission to expose credentials or OTPs.

Should I use a real account to create a documentation screenshot?

Prefer a synthetic or authorized test context. Do not share banking IDs, passwords, PINs, or OTPs, as RBI advises against sharing them.

When should I use full-page capture?

Only when the whole scrollable page is required. Otherwise use a locator screenshot, clip, or the default viewport and review exactly what the image contains.