ScreenshotNeo

BlogHow-to

Playwright Full-Page Screenshot Cut Off in Hindi: How to Fix It

Fix a Playwright screenshot that cuts off the page or clips Hindi text. Diagnose capture size, page readiness, CSS, fonts, and unstable rendering.

By the ScreenshotNeo team4 October 20269 min read

A Playwright full-page screenshot that looks “cut off” can describe two different problems: the image is missing part of the page, or the page is present but Hindi characters or lines are clipped inside their text boxes. Start with fullPage: true (Python: full_page=True) and wait for the application’s content-ready signal. Then identify which symptom you have before changing CSS or browser settings. There is no evidence in the sources below that Hindi itself causes a general Playwright full-page screenshot defect.

1. Take a full-page baseline

Playwright screenshots capture the visible viewport by default. Set fullPage: true to capture the full scrollable page. The Python API spells this option full_page. See the Playwright screenshot API.

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

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  // Replace this with the signal that means your app's content is ready.
  await page.locator('main').waitFor({ state: 'visible' });
  await page.screenshot({ path: 'page.png', fullPage: true });
  await browser.close();
})();

This is a runnable baseline for a page with a visible main element. If your page has no such element, replace that wait with an application-specific condition; examples follow.

2. Identify what is actually cut off

What you see Likely area to inspect
Bottom or right edge of the document is missing Capture option, explicit crop, document dimensions, nested scrolling, late content, or page layout changes during capture.
Page continues, but Hindi glyphs or lines are cropped inside a box Font availability, computed font, line height, fixed height, overflow, or other CSS constraints.
Different runs omit or shift different content Asynchronous content, lazy loading, animations, sticky or fixed elements, or an inconsistent browser/OS/font environment.

Save both a normal viewport image and a full-page image. If the viewport image already shows clipped letters, fullPage is not the cause. If the viewport is correct but the full-page image loses a page edge, inspect the page extent and capture options.

3. Wait for the page content you need

Navigation completing does not necessarily mean your application has finished rendering its data. Prefer a condition tied to the actual content over an arbitrary longer timeout.

await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.locator('[data-testid="article-content"]').waitFor({ state: 'visible' });
await page.screenshot({ path: 'page.png', fullPage: true });

Other useful readiness checks include waiting for a specific heading, a loading indicator to disappear, or a known application event. Use networkidle only when it fits the site: analytics, polling, and persistent connections can prevent network activity from becoming idle. A fixed delay can be a temporary diagnostic, but it is not a reliable substitute for knowing that the required content exists.

4. Check the page dimensions, crop, and scroll container

Playwright’s clip option explicitly crops a screenshot to a rectangle. Remove it while diagnosing a full-page capture, or verify that its x, y, width, and height are intentional. The API documents both clip and fullPage; do not add a crop when the goal is the full document.

const dimensions = await page.evaluate(() => ({
  viewport: { width: innerWidth, height: innerHeight },
  document: {
    width: document.documentElement.scrollWidth,
    height: document.documentElement.scrollHeight
  },
  body: {
    width: document.body.scrollWidth,
    height: document.body.scrollHeight
  }
}));
console.log(dimensions);
await page.screenshot({ path: 'full.png', fullPage: true });

Compare the reported document dimensions with the visible content and expected screenshot size. Look for a wrapper with height or max-height plus overflow: auto or overflow: hidden. A full-page capture concerns the page’s scrollable document; content that scrolls inside a nested element may need a separate element capture or a deliberate approach to that container.

Also check whether the site adds content as you scroll. Lazy-loaded sections and images may not exist at their final dimensions until they enter view. If needed, scroll through the document and wait for the relevant content before returning to the top and capturing; verify the resulting document height rather than assuming every lazy-loading implementation behaves the same way.

5. Diagnose clipped Hindi text

When the page edges are intact but Devanagari characters are cut within a paragraph, inspect the rendered element and its CSS. These checks are diagnostic hypotheses, not proof of a Hindi-specific Playwright bug.

  1. Check the computed font. Confirm that the intended font-family is applied to the text element, and that a suitable Devanagari-capable font is available in the environment running the browser.
  2. Wait for fonts before capturing. Use await page.evaluate(() => document.fonts.ready). If a web font is expected, inspect whether it actually loaded; waiting cannot make an unavailable font appear.
  3. Check the box and line rules. Inspect computed height, max-height, overflow, line-height, and any clipping, transforms, or fixed positioning on the element and its ancestors.
  4. Compare in the same environment. Run the capture with the same browser, operating system, and installed fonts as the known-good capture.
const textDiagnostics = await page.locator('.hindi-copy').evaluate(element => {
  const style = getComputedStyle(element);
  const rect = element.getBoundingClientRect();
  return {
    text: element.textContent,
    fontFamily: style.fontFamily,
    fontSize: style.fontSize,
    lineHeight: style.lineHeight,
    height: style.height,
    maxHeight: style.maxHeight,
    overflow: style.overflow,
    clientHeight: element.clientHeight,
    scrollHeight: element.scrollHeight,
    renderedHeight: rect.height
  };
});
console.log(textDiagnostics);
console.log('Fonts ready:', await page.evaluate(() => document.fonts.ready.then(() => true)));
console.log('Expected font available:', await page.evaluate(() => document.fonts.check('16px "Your Devanagari Font"')));

Replace .hindi-copy and the sample font family with the page’s actual selector and intended font. A positive font check helps diagnose availability; it does not establish that every glyph uses that font or that the box has adequate height. If the intended font is absent in CI or a container, make it available to that environment and rerun the comparison.

6. Compare stable captures

Keep browser, operating system, browser version, installed fonts, viewport, and headless settings consistent when comparing images. Playwright notes that rendering can vary across host operating systems, browser versions, settings, hardware, and headless mode; its visual comparison guide recommends using the same environment as the baseline.

For Playwright Test visual assertions, toHaveScreenshot() waits for two consecutive screenshots to match before comparing with the expected image. That can help with transient visual output, but it cannot fix a genuinely clipped text box or missing page content.

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

test('article screenshot is stable', async ({ page }) => {
  await page.goto('https://example.com/article');
  await page.locator('[data-testid="article-content"]').waitFor({ state: 'visible' });
  await expect(page).toHaveScreenshot('article.png', { fullPage: true });
});

7. Complete runnable examples

JavaScript with Playwright

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

(async () => {
  const browser = await chromium.launch();
  try {
    const page = await browser.newPage({ viewport: { width: 1365, height: 900 } });
    await page.goto('https://example.com/article', { waitUntil: 'domcontentloaded' });
    await page.locator('main').waitFor({ state: 'visible' });
    await page.evaluate(() => document.fonts.ready);
    await page.screenshot({ path: 'article.png', fullPage: true });
  } finally {
    await browser.close();
  }
})();

Install the Playwright package and its browser for your project using the official installation guide. Replace the example URL and readiness selector with the target page and its real content-ready condition.

Python with Playwright

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch()
        try:
            page = await browser.new_page(viewport={"width": 1365, "height": 900})
            await page.goto("https://example.com/article", wait_until="domcontentloaded")
            await page.locator("main").wait_for(state="visible")
            await page.evaluate("() => document.fonts.ready")
            await page.screenshot(path="article.png", full_page=True)
        finally:
            await browser.close()

asyncio.run(main())

cURL and Node.js with ScreenshotNeo

If you need the resulting screenshot without managing a browser installation, ScreenshotNeo provides a screenshot API. These calls use the product’s documented API pattern; add your own API key and choose the target URL. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/article -o shot.webp
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/article' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await require('node:fs/promises').writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));

The Node.js example runs in a modern Node environment with global fetch. Keep the API key on the server; do not expose it in client-side page code. ScreenshotNeo supports full-page capture and custom CSS and JavaScript, among its capture options.

8. Troubleshooting common errors

Symptom or error Likely cause What to do
Only the viewport is saved fullPage was omitted or is false. Set fullPage: true in JavaScript or full_page=True in Python.
The bottom or right edge is missing Explicit clip, document sizing, or content inside a nested scroller. Remove the crop, inspect scroll dimensions and overflow rules, and determine which element actually scrolls.
Hindi letters are clipped but the page is complete Font fallback or CSS box/line clipping. Inspect computed font and text-box styles; verify the intended font is available and wait for it to load.
Content appears in some runs only Capture occurs before application data or lazy content is ready, or layout changes during capture. Wait for a page-specific readiness signal, then compare repeat captures under stable conditions.
Visual test fails across machines Rendering, fonts, browser, OS, or headless settings differ. Run the baseline and comparison in the same environment and review whether the difference is a real regression.
Screenshot call times out The page or browser is busy, or the page is unusually large. First check that navigation and readiness waits can complete; capture a smaller diagnostic page or viewport to isolate the bottleneck. Do not treat a larger timeout as proof the image is correct.
The screenshot includes a loading state Navigation ended before the app populated the required content. Wait for a content-specific selector or state transition before capture.

A historical Playwright issue documents intermittent cutoffs and shifts in one reported setup: Linux, the Playwright v1.30.0 focal image, Node.js v16.19.0, and Chromium in CI. It shows that reports of flaky full-page captures exist, but does not establish a current universal bug or a Hindi-specific cause. See the issue report.

9. Performance, reliability, and cost

  • Large pages take more resources. A full-page image can be much larger than a viewport capture. For diagnosis, use a viewport capture or targeted element capture first, then capture the full page when required.
  • Readiness checks improve reliability. A selector or application state tied to the content is more repeatable than adding an arbitrary delay. Avoid waiting for network idle on sites that continuously send requests unless that condition is appropriate.
  • Fonts are part of the test environment. A missing font can change line wrapping and element height, affecting both Hindi rendering and page dimensions.
  • Use a controlled baseline. Keep the browser and host environment aligned between baseline generation and comparison; investigate environmental differences before changing an expected screenshot.
  • Self-hosted cost. Playwright itself does not price each screenshot in the code shown here, but your browser execution consumes your own compute and storage resources. The exact cost depends on your infrastructure and capture workload.

Or skip the browser setup

ScreenshotNeo takes a screenshot with one API request. For this target, substitute your URL and API key:

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

ScreenshotNeo accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, and failed loads are never billed, and cache hits cost nothing. An MCP server lets AI agents use screenshot and page-information tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Read the API documentation or learn about ScreenshotNeo, then sign up for 1,000 free screenshots a month with no card.

FAQ

Does Playwright need a Hindi font installed?

The browser environment needs access to the font intended by the page, or a suitable fallback, to render those glyphs as expected. Verify the computed font and whether the expected font loaded in the capture environment.

Is there a known Hindi-specific Playwright full-page bug?

The cited documentation and issue report do not establish one. Diagnose page-edge truncation separately from text-box clipping before attributing the problem to Playwright or Hindi.

Will toHaveScreenshot() fix cut-off text?

No. It waits for consecutive captures to stabilize before comparing them. It can help with transient output, but CSS clipping or absent content still needs to be fixed at its source.