ScreenshotNeo

BlogHow-to

How to Use Playwright to Screenshot an Indian Ecommerce Page in Bengali

Capture an Indian ecommerce page with Bengali text using Playwright. Wait for fonts and real page content, then choose a viewport, full-page, or element screenshot.

By the ScreenshotNeo team4 October 202610 min read

Use Playwright to open the store page, wait for the product content you care about, wait for the page’s fonts to finish loading, and then call page.screenshot(). For a full catalog or product page, set fullPage: true; for one product card, take a locator screenshot. Bengali characters are page text: Playwright captures what the browser rendered, so a Bengali-capable font must be available and loaded before capture.

The examples below use a public product listing as a placeholder. Replace STORE_URL and PRODUCTS_SELECTOR with a URL and stable selector for a page you are authorized to access. The store is unspecified, so no selector, language switch, or consent behavior can be assumed.

1. Install Playwright and its browser

For the JavaScript example, create a project and install Playwright, then install its Chromium browser. Use the official Playwright installation instructions for your environment.

npm init -y
npm install playwright
npx playwright install chromium

Save the following as screenshot-store.js. Set the URL and selector in the environment, then run it with Node.js:

STORE_URL='https://example.com/replace-with-store-page' PRODUCTS_SELECTOR='main' node screenshot-store.js

Use an actual product-grid or product-detail selector when possible. The broad main selector is only a runnable fallback; it may match a large area or a generic page container.

2. Capture a Bengali ecommerce page with JavaScript

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

async function main() {
  const url = process.env.STORE_URL;
  const contentSelector = process.env.PRODUCTS_SELECTOR || 'main';

  if (!url) {
    throw new Error('Set STORE_URL to the public ecommerce page to capture.');
  }

  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({
      viewport: { width: 1440, height: 1000 },
      deviceScaleFactor: 1,
      locale: 'bn-IN',
    });

    await page.goto(url, { waitUntil: 'load', timeout: 60000 });

    // Wait for the page-specific content, not just the navigation event.
    const content = page.locator(contentSelector).first();
    await content.waitFor({ state: 'visible', timeout: 30000 });

    // Wait for web fonts used by the rendered page, including Bengali fonts.
    await page.evaluate(() => document.fonts.ready);

    await page.screenshot({
      path: 'store-bengali.png',
      fullPage: true,
      type: 'png',
      scale: 'css',
      animations: 'disabled',
    });
  } finally {
    await browser.close();
  }
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});

The script sets the browser locale to bn-IN, but this does not force a store to serve a Bengali translation. If the site has a language selector or locale-specific URL, use its normal, authorized flow before taking the screenshot. The selector wait and document.fonts.ready address different readiness conditions: the first waits for meaningful content, while the second waits for the document’s fonts to settle.

Playwright’s screenshot guide shows viewport, full-page, and locator screenshots. The Page API lists screenshot options and navigation behavior.

3. Run the equivalent workflow in Python

If your automation project uses Python, install the Python package and browser binaries following the official Python setup guide. Save this asynchronous example as screenshot_store.py:

import asyncio
import os
from playwright.async_api import async_playwright

async def main():
    url = os.environ.get("STORE_URL")
    content_selector = os.environ.get("PRODUCTS_SELECTOR", "main")
    if not url:
        raise RuntimeError("Set STORE_URL to the public ecommerce page to capture.")

    async with async_playwright() as p:
        browser = await p.chromium.launch()
        try:
            page = await browser.new_page(
                viewport={"width": 1440, "height": 1000},
                device_scale_factor=1,
                locale="bn-IN",
            )
            await page.goto(url, wait_until="load", timeout=60000)
            await page.locator(content_selector).first.wait_for(
                state="visible", timeout=30000
            )
            await page.evaluate("() => document.fonts.ready")
            await page.screenshot(
                path="store-bengali.png",
                full_page=True,
                type="png",
                scale="css",
                animations="disabled",
            )
        finally:
            await browser.close()

asyncio.run(main())

For installation, screenshot options, and sync or async variants, see Playwright’s Python screenshot guide.

4. Make sure Bengali text is actually ready

A screenshot records pixels, not the intended language or font. If the store uses a web font for Bengali, the browser may initially show blank text or fallback text while that font loads. Google’s web font technical notes describe these loading differences across browsers. Waiting for document.fonts.ready helps avoid capturing during font loading, but it cannot repair a missing font, a failed font request, or a page whose CSS does not select a Bengali-capable family.

  • Inspect the resulting image at its intended display size for missing-glyph boxes, clipped vowel signs, or fallback lettering.
  • Check the browser’s console and network activity if the page’s font request fails.
  • If you control the page, select a Bengali-capable font and include a fallback family. Noto Sans Bengali is one available family; verify it with the actual text and page layout.
  • If the page uses a language switch, wait for the Bengali content itself to appear before waiting for fonts and capturing.

Do not add a fixed sleep as the normal readiness strategy. A delay can be too short on a slow run and waste time on a fast one. Wait for a page-specific visible element and the browser font set instead. Playwright discourages timeout waits in production workflows; see the Page API guidance.

5. Choose the screenshot area and output

Need Playwright option Result
What is currently visible page.screenshot({ path: 'viewport.png' }) The current viewport; this is the default.
Everything in the scrollable document page.screenshot({ path: 'full.png', fullPage: true }) A tall capture of the full page.
One product card or other component page.locator('.product-card').screenshot({ path: 'product.png' }) The selected element, scrolled into view if needed.
A known rectangular region page.screenshot({ path: 'region.png', clip: { x: 0, y: 0, width: 900, height: 700 } }) The specified rectangle in page coordinates.

Use a real selector for the element screenshot. A CSS selector such as .product-card is only an example; ecommerce sites use different markup. Locator screenshots capture the matched element rather than all the other page content.

Format, dimensions, and scale

  • PNG: a sensible default for crisp text and visual inspection. PNG does not use the lossy quality setting.
  • JPEG: useful when a smaller lossy image is acceptable. Set quality from 0 to 100 if you need to control the tradeoff.
  • WebP: supported as a screenshot output type; choose quality according to whether you need lossless or lossy output.
  • scale: 'css': one output pixel per CSS pixel. This keeps the output smaller when a high-DPI device scale is unnecessary.
  • scale: 'device': one output pixel per device pixel. This can create a larger image on high-DPI settings.
  • fullPage: includes content below the fold; omit it for a viewport-only capture.
  • clip: captures a rectangle. Do not combine it with fullPage unless the API version and options you use support that combination.
  • animations: 'disabled': reduces movement during capture. Keep it if repeatable visual output matters; omit it if the animation state itself is what you need to document.

Refer to the Playwright screenshot API for the complete option list for your installed version. Capture defaults and option availability can vary by language binding and version.

A full-page screenshot captures the scrollable document, but a store may load product images only when they approach the viewport. If images are missing, scroll through the page before capture so lazy-loaded content has a chance to load, or wait for the specific images you need. A targeted readiness check could look for a known product image to finish loading:

await page.locator('.product-card img').first().waitFor({ state: 'visible' });
await page.waitForFunction(() => {
  const image = document.querySelector('.product-card img');
  return image instanceof HTMLImageElement && image.complete && image.naturalWidth > 0;
});

Replace that selector with the actual page markup. For many lazy images on a very long catalog, scroll incrementally and wait for the images that matter rather than assuming navigation completion means every image is loaded.

Consent dialogs and overlays are site-specific. For reliable or authorized capture, follow the site’s normal access and consent flow. Do not bypass access controls or capture content you are not permitted to access. If you only need a page section, an element screenshot can avoid unrelated page regions, but it does not grant access to protected content.

7. Improve repeatability and control

Browser screenshots can differ between operating systems, browser versions, font installations, browser modes, viewport settings, and other host configuration. Playwright’s visual comparison guidance recommends accounting for environment differences when comparing images. For reproducible captures, keep these inputs fixed:

  1. Use the same Playwright version and its matching browser binary.
  2. Use the same operating system or container image and installed fonts.
  3. Set the viewport and deviceScaleFactor explicitly.
  4. Keep browser locale, color scheme, and other context options consistent.
  5. Wait on stable content and fonts, rather than timing the screenshot by an arbitrary delay.
  6. Use a consistent output format and screenshot scale.

To request dark mode, set colorScheme: 'dark' on the browser context or page when supported by the page’s styling. To capture a mobile layout, use a narrower viewport or a documented device preset, then confirm that the site has actually switched to its mobile layout. Locale is not a translation switch: bn-IN affects browser locale signals, but the store decides what content to serve.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API. One GET request returns an image or PDF, and the parameter names other screenshot APIs use also work, which makes switching easy. See the ScreenshotNeo API documentation for request options.

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

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Replace the example URL with the public page you are allowed to capture. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and the Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card.

9. Troubleshooting

Problem Likely cause What to try
Bengali letters appear as boxes or fallback glyphs A Bengali-capable font is unavailable, its request failed, or the capture happened before it finished loading. Check the font request and computed font family, wait for document.fonts.ready, then inspect the saved image. If you control the page, provide a Bengali-capable font and fallback.
Some text is blank A web font may still be loading; browser behavior during font loading varies. Wait for the document fonts and check for failed font requests. The browser may render blank text or fallback text while loading.
The screenshot has a header but no products The navigation event completed before the app rendered its product data. Wait for a stable product-grid selector to become visible; if needed, wait for a known product response or image condition too.
Images are missing in a full-page capture Images may be lazy-loaded or still downloading. Scroll through the relevant content and wait for important images to report complete with a nonzero natural width before capture.
The script times out waiting for a selector The selector may be wrong, absent in that locale, hidden, or blocked by a redirect or consent flow. Inspect the page and choose a stable selector that exists after the authorized page flow. Do not merely increase the timeout without checking the cause.
The image differs on another machine Rendering inputs such as OS, browser version, fonts, viewport, or headless environment changed. Pin the capture environment and context settings before comparing screenshots.
The output file is unexpectedly large Device-pixel scaling and full-page height multiply output dimensions. Use scale: 'css', capture an element or viewport instead of the entire document, or select a compressed format if loss is acceptable.
Navigation fails or shows a challenge The store may be unavailable, require normal consent or login, or restrict automated traffic. Check the URL and response, use only authorized access, and follow the site’s normal flow. Do not try to evade its protections.

10. Performance, reliability, and cost

A local Playwright capture has no per-screenshot API charge, but your workflow still uses compute, browser storage, and network bandwidth; operating a capture service also means maintaining the browser installation and runtime. Full-page captures and device-scale output can require more memory and produce larger files than viewport or CSS-scale captures. Use the smallest area and resolution that meet the task.

Reliability depends on the target page as well as the script. Product availability, inventory, promotions, network conditions, fonts, and dynamic widgets can change between runs. For a recurring capture, record the target URL and timestamp alongside the image, use explicit readiness checks, and decide how to handle navigation errors and missing content. Keep the browser and operating system fixed when comparing output. No universal runtime or image-size benchmark applies to an unspecified store page.

ScreenshotNeo pricing is Free for 1,000 shots per month with no card; Starter is $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, and every feature is on every plan. Its responses identify the page verdict and billing status in headers, and only clean shots are billed; cache hits also cost nothing. Consult the docs for current request details.

Frequently asked questions

Does setting locale: 'bn-IN' translate an ecommerce page?

No. It sets the browser locale signal. The site controls the language it serves, so use the site’s normal language selector or locale URL when needed.

Can Playwright make Bengali text sharper?

Choose PNG and an appropriate viewport and scale for crisp text. The font and the browser’s rendered glyphs still determine how the characters look; a screenshot option cannot add missing Bengali glyphs.

Should I capture the whole page or just the product grid?

Use a full-page screenshot when below-the-fold content matters. Use a locator screenshot when the product grid or one card is the subject and unrelated page content is not needed.

Can I use this for a page behind a login?

Only if you are authorized to access and capture it. Use the site’s normal login flow and protect any session credentials used by your script.