ScreenshotNeo

BlogHow-to

How to capture Playwright screenshots of a responsive Indian banking website

Capture repeatable desktop and mobile screenshots of an authorized banking test site with Playwright. Choose the right capture mode and protect sensitive data.

By the ScreenshotNeo team4 October 202611 min read

Use Playwright with an explicitly configured desktop viewport and a mobile device profile to capture responsive layouts. Choose a viewport screenshot for breakpoint checks, a full-page screenshot for long pages, or a locator screenshot for one component. Run captures only against a bank-owned or otherwise authorized test environment, use synthetic data, and mask sensitive fields where needed.

This guide uses Playwright Test with TypeScript. It also includes equivalent command-line, Python, and Node.js capture examples. The example routes, selectors, and device profile are placeholders: replace them with values from your authorized test application.

1. Confirm scope and protect data

Before automating a banking site, confirm the approved test URL, pages, states, and login flow with the site owner. A publicly reachable login page does not establish permission to automate against production or access an account.

  • Prefer a staging or demo environment populated with synthetic account details.
  • Do not capture real credentials, balances, transaction history, customer identifiers, or one-time passwords.
  • If a sensitive-looking field must be present in a screenshot, mask it or use a test page designed for safe capture.
  • Store screenshots in access-controlled test storage and follow the bank’s retention and sharing policy.

RBI materials emphasize confidentiality of customer information. Its digital payment security direction applies to regulated entities and digital payment products and services; it is not a Playwright-specific screenshot rule. The DPDP Act text includes lawful-purpose grounds and a bank website example, while commencement and applicability depend on government notification. Check current requirements for the particular organization and activity. See the RBI digital payment security controls, the RBI customer confidentiality guidance, and the DPDP Act and framework materials.

2. Set up Playwright

For a new project, install Playwright Test and its browser binaries:

npm init playwright@latest
npx playwright install chromium

Set the authorized test site’s base URL in the shell or CI environment. Do not put credentials in source code or screenshot filenames.

export TEST_BASE_URL="https://your-authorized-staging.example"
mkdir -p artifacts

Use your own approved staging hostname in place of the example. The code below expects Chromium and the @playwright/test package.

3. Capture desktop and mobile views

This runnable Playwright Test example captures two routes at desktop size and a mobile login view. The main readiness locator is illustrative; replace it with a stable selector that indicates the intended page state in your app. The mobile test uses a Playwright device descriptor and masks a password input if one is present.

import { test, devices } from '@playwright/test';

const baseURL = process.env.TEST_BASE_URL;
if (!baseURL) throw new Error('Set TEST_BASE_URL to an authorized test URL');

const routes = [
  { name: 'home', path: '/' },
  { name: 'login', path: '/login' },
];

test.describe('authorized responsive screenshot captures', () => {
  for (const route of routes) {
    test(`${route.name} desktop`, async ({ page }) => {
      await page.setViewportSize({ width: 1440, height: 900 });
      await page.goto(new URL(route.path, baseURL).toString(), {
        waitUntil: 'domcontentloaded',
      });
      // Replace with the application's stable, meaningful readiness condition.
      await page.locator('main').waitFor({ state: 'visible' });
      await page.screenshot({
        path: `artifacts/${route.name}-desktop-1440x900.png`,
        animations: 'disabled',
        scale: 'css',
      });
    });
  }
});

test('authorized mobile login view', async ({ browser }) => {
  const context = await browser.newContext({ ...devices['iPhone 13'] });
  const page = await context.newPage();
  await page.goto(new URL('/login', baseURL).toString(), {
    waitUntil: 'domcontentloaded',
  });
  // Replace with the application's stable, meaningful readiness condition.
  await page.locator('main').waitFor({ state: 'visible' });
  await page.screenshot({
    path: 'artifacts/login-mobile-full.png',
    fullPage: true,
    animations: 'disabled',
    scale: 'css',
    mask: [page.locator('input[type="password"]')],
  });
  await context.close();
});

Run the captures with:

npx playwright test

Confirm the selected device descriptor exists in your installed Playwright version. A device descriptor sets properties such as viewport, screen size, user agent, and touch capability; you can override the viewport when needed. See the Playwright emulation guide and screenshot documentation.

4. Choose the screenshot scope

Review goal Playwright API Result
Check a responsive breakpoint page.screenshot() The visible viewport at the configured dimensions.
Document a long page page.screenshot({ fullPage: true }) The full scrollable page in one image.
Review a panel or form locator.screenshot() The matched element, useful for focused component review.
Produce high-DPI pixels scale: 'device' Device-pixel output, which can be larger than CSS-pixel output.
Conceal a field in the image mask: [locator] A mask covers the selected element’s bounding box in the screenshot.

For a component capture, wait for and screenshot a locator after the page reaches its intended state:

const panel = page.locator('[data-testid="account-summary"]');
await panel.waitFor({ state: 'visible' });
await panel.screenshot({
  path: 'artifacts/account-summary-mobile.png',
  animations: 'disabled',
  scale: 'css',
});

Use a test-only selector such as a data-testid where possible. A broad selector like main is easy to demonstrate but may match the wrong element or become unstable as the page changes.

5. Configure repeatable responsive captures

Viewport and device profile

Use an explicit desktop viewport and a named mobile device profile for repeatable runs. The viewport controls the layout dimensions; a device profile can also emulate related browser properties such as touch and user agent. Device emulation is useful for responsive review without a physical phone, but it does not replace testing on real hardware when hardware-specific behavior matters.

Full page versus viewport

A viewport screenshot captures what is visible at that scroll position. A full-page screenshot captures the page’s scrollable content and can be very tall. For breakpoint comparisons, keep the viewport dimensions identical across runs and prefer viewport captures; use full-page images for reading or documenting the whole layout.

Scale and animations

scale: 'css' sizes the output in CSS pixels and can make images more compact and aligned with CSS layout dimensions. scale: 'device' uses device pixels and may produce a larger file. animations: 'disabled' reduces variation from animations during capture. It does not make dynamic data, rotating content, timestamps, or network responses deterministic.

Readiness and page state

Navigation completion is not the same as application readiness. After navigation, wait for a page-specific condition such as a visible heading, loaded test fixture, or completion marker. Prefer that condition over a fixed sleep; arbitrary delays can be too short on a slow run and waste time on a fast one. Use only a selector and state appropriate to the authorized test page.

Masking

Playwright screenshot masking covers the bounding boxes of specified locators. It is a useful safeguard for a test capture, but it does not remove sensitive data from the application or make an unsafe test flow appropriate. Prefer synthetic data and verify the resulting artifact before sharing it.

6. Capture with Python or plain Node.js

Playwright’s primary example above uses TypeScript and Playwright Test. These standalone alternatives show the same basic browser workflow in Python and Node.js. Install the corresponding Playwright package and browser first.

Python

import os
from pathlib import Path
from playwright.sync_api import sync_playwright

base_url = os.environ.get("TEST_BASE_URL")
if not base_url:
    raise RuntimeError("Set TEST_BASE_URL to an authorized test URL")

Path("artifacts").mkdir(exist_ok=True)

with sync_playwright() as p:
    browser = p.chromium.launch()
    desktop = browser.new_page(viewport={"width": 1440, "height": 900})
    desktop.goto(base_url.rstrip("/") + "/login", wait_until="domcontentloaded")
    desktop.locator("main").wait_for(state="visible")
    desktop.screenshot(
        path="artifacts/login-desktop-1440x900.png",
        animations="disabled",
        scale="css",
    )

    # Use a descriptor available in the installed Python Playwright version.
    mobile_options = p.devices["iPhone 13"]
    mobile = browser.new_page(**mobile_options)
    mobile.goto(base_url.rstrip("/") + "/login", wait_until="domcontentloaded")
    mobile.locator("main").wait_for(state="visible")
    mobile.screenshot(
        path="artifacts/login-mobile-full.png",
        full_page=True,
        animations="disabled",
        scale="css",
        mask=[mobile.locator('input[type="password"]')],
    )
    browser.close()

Install and run, for example:

python -m pip install playwright
python -m playwright install chromium
python capture.py

Node.js

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

const baseURL = process.env.TEST_BASE_URL;
if (!baseURL) throw new Error('Set TEST_BASE_URL to an authorized test URL');
await mkdir('artifacts', { recursive: true });

const browser = await chromium.launch();
const desktop = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await desktop.goto(new URL('/login', baseURL).toString(), { waitUntil: 'domcontentloaded' });
await desktop.locator('main').waitFor({ state: 'visible' });
await desktop.screenshot({
  path: 'artifacts/login-desktop-1440x900.png',
  animations: 'disabled',
  scale: 'css',
});

const mobileContext = await browser.newContext({ ...devices['iPhone 13'] });
const mobile = await mobileContext.newPage();
await mobile.goto(new URL('/login', baseURL).toString(), { waitUntil: 'domcontentloaded' });
await mobile.locator('main').waitFor({ state: 'visible' });
await mobile.screenshot({
  path: 'artifacts/login-mobile-full.png',
  fullPage: true,
  animations: 'disabled',
  scale: 'css',
  mask: [mobile.locator('input[type="password"]')],
});
await mobileContext.close();
await browser.close();

Install and run the Node.js example with:

npm install playwright
npx playwright install chromium
node capture.mjs

7. Run a responsive capture matrix

For a useful layout review, capture a small, deliberate matrix instead of taking many nearly identical images. Include the page state and viewport in each artifact name so reviewers can tell what they are comparing.

Dimension Record Why it matters
Route and UI state For example, login form or synthetic account summary Different states can change layout and content.
Viewport or device Width, height, and device profile Separates responsive changes from setup differences.
Browser project Chromium, Firefox, or WebKit when included in the test suite Browser engines can render differently.
Screenshot scope Viewport, full page, or locator Defines which part of the page is being reviewed.
Image scale and animation treatment CSS or device scale; animations enabled or disabled Helps explain output size and visual variation.

A filename such as account-summary-mobile-390x844-chromium.png carries useful context. Add a capture date or build identifier when artifacts need to be compared across releases. Keep file names free of personal or account data.

8. cURL example for a hosted capture

If you already have a hosted test URL and need an image without setting up a local browser, ScreenshotNeo accepts one GET request for a screenshot. Use it only with a URL and page state you are authorized to capture. This basic request captures the URL; configure any required state or capture options through the documented API parameters.

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

See the ScreenshotNeo API documentation for parameters and configuration.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns a PNG, JPEG, WebP, or PDF. For an authorized page, the basic 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

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and whether the shot was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan. Use synthetic or otherwise approved content for banking screenshots, and review the output before storing or sharing it.

Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.

9. Troubleshooting

Symptom Likely cause Fix
TEST_BASE_URL error The environment variable is missing or empty. Set it to the authorized test site’s base URL before running the script.
Navigation fails or reaches an unexpected page Wrong base URL, redirect, unavailable staging environment, or an unhandled authentication flow. Check the approved URL and test setup; handle only the intended, authorized flow and verify the final page state.
Timeout waiting for main The selector does not exist, is hidden, or does not indicate readiness for that route. Inspect the test page and use a stable selector that becomes visible when the required state is ready.
Screenshot is blank or incomplete The capture ran before the application rendered its meaningful content, or the chosen selector does not match the page. Wait for the app-specific readiness condition and verify the target element before capture.
Mobile screenshot looks like desktop The mobile context was not created from the device descriptor, or the app’s layout breakpoint differs from the assumed dimensions. Confirm the descriptor and viewport in the running Playwright version; record the actual dimensions and check the site’s responsive rules.
Mask does not cover the intended value The locator matches a different element, is hidden, or the sensitive value is rendered elsewhere. Use a precise locator, check its visibility and screenshot bounds, and prefer synthetic data. Verify the artifact before sharing.
Screenshots differ between runs Dynamic content, animation, timestamps, ads, or data responses changed. Use fixed test data and state, disable animations, and wait for specific content. Keep browser, viewport, route, and scale constant.
Device name is unavailable The installed Playwright version does not include that descriptor. Check the installed version’s device list and select a supported descriptor or configure the viewport and emulation settings explicitly.
Browser executable missing The package is installed but its browser binaries are not. Run the appropriate Playwright install command for the language and browser engine.

10. Performance, reliability, and cost

Local Playwright captures consume browser and machine resources. Full-page images can be large and take longer to capture than a viewport or component image. Use the narrowest scope that answers the review question, reuse a browser process for batches, and avoid launching unnecessary browser instances. Explicit readiness conditions improve reliability and avoid both premature captures and wasted fixed-delay waits.

ScreenshotNeo pricing is Free: 1,000 shots per month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free. All features are available on every plan. Compare the number of captures you need with the plan allowance; no external price or performance comparison is implied here.

For sensitive banking pages, treat every artifact as potentially confidential even when masking is enabled. Use approved storage, restrict access, and follow the site owner’s handling and retention requirements. Screenshot automation does not establish permission to access a page or account.

11. FAQ

Can Playwright take a responsive screenshot without a real phone?

Yes. A Playwright device descriptor and explicit viewport can emulate common mobile browser properties for repeatable layout captures. Physical-device testing remains useful for hardware-specific behavior.

Should I capture the whole banking page or only the viewport?

Use the viewport to compare responsive breakpoints and the full page to document long content. Use a locator screenshot when reviewing one form, panel, or component.

Is masking enough to make a screenshot safe to share?

No. Masking covers selected element bounds in the image, but synthetic data and the site’s approved data-handling process should remain the default. Inspect each artifact before sharing.

Can I run this against a live bank website?

Only if the site owner has explicitly authorized the target, pages, and automation. A public URL alone does not grant that permission.