How to Capture a Website Screenshot with Playwright on Windows in India
Install Playwright on Windows, capture a viewport, full page or element, and save the result with a runnable Node.js script.
To capture a website screenshot with Playwright on Windows, install the Playwright Node.js package and its browser binaries, navigate to the page, then call page.screenshot(). The script below saves a full-page PNG. Remove fullPage: true to capture only the viewport, or use a locator screenshot to capture one element.
The instructions are the same in India as elsewhere: the official Playwright setup does not specify an India-specific workflow. You need a supported Windows environment, Node.js, and the matching browser binaries. See the current Playwright installation guide for version requirements; at the time of research it lists Node.js 22.x, 24.x or 26.x, and Windows 11+, Windows Server 2019+ or WSL.
1. Install Playwright on Windows
Open PowerShell in a folder for your project. Initialize a Node.js project, install Playwright, and download the Chromium browser binary:
mkdir website-screenshots
cd website-screenshots
npm init -y
npm install playwright
npx playwright install chromium
For Chromium, Firefox and WebKit, run npx playwright install instead. Playwright browser downloads are tied to the installed Playwright version, so run the install command again after upgrading the package if the browser is missing or incompatible. Windows browser binaries are normally stored under %USERPROFILE%\AppData\Local\ms-playwright. The browser installation guide covers browser installation, cache locations and proxy configuration.
2. Save a full-page screenshot
Create screenshot.js with this complete CommonJS script. It opens Chromium in headless mode, navigates to the target URL, waits for the page load event, captures the whole scrollable page and closes the browser even if capture fails.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto('https://example.com', {
waitUntil: 'load',
timeout: 60000,
});
await page.screenshot({
path: 'website-full.png',
fullPage: true,
animations: 'disabled',
});
console.log('Saved website-full.png');
} finally {
await browser.close();
}
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});
Run it from PowerShell:
node screenshot.js
path determines the output file. PNG is the default format, and the filename extension selects JPEG or WebP when you use .jpg or .webp. Without fullPage: true, Playwright captures the current viewport. The official screenshot guide documents the screenshot API and examples.
3. Choose the capture type
| Need | Playwright code | What it captures |
|---|---|---|
| Viewport | await page.screenshot({ path: 'viewport.png' }); |
The visible browser page at the current viewport size. |
| Full page | await page.screenshot({ path: 'full.png', fullPage: true }); |
The full scrollable page, including content below the fold. |
| One element | await page.locator('.header').screenshot({ path: 'header.png' }); |
The element matched by the locator, cropped to its bounds. |
| Clipped area | await page.screenshot({ path: 'crop.png', clip: { x: 0, y: 0, width: 800, height: 600 } }); |
A rectangle in page coordinates. |
For an element capture, wait until the target exists and is visible. A robust example:
const header = page.locator('header');
await header.waitFor({ state: 'visible', timeout: 15000 });
await header.screenshot({ path: 'header.png' });
If a locator matches more than one element, make it specific with a unique selector or a locator such as page.getByRole('banner'). Locator screenshots scroll the element into view when needed. A clip rectangle uses page coordinates, so its position and size should fit the rendered page.
4. Set image format, size and browser behavior
PNG, JPEG and WebP
Playwright supports PNG, JPEG and WebP screenshots. PNG is the default and is suitable when you want lossless capture. JPEG is lossy and accepts a quality value from 0 to 100. WebP can also be selected by the filename extension. For example:
await page.screenshot({ path: 'page.jpg', type: 'jpeg', quality: 80 });
await page.screenshot({ path: 'page.webp', type: 'webp', quality: 80 });
Use a format supported by your next tool or destination. The browser and operating system affect rendering, so do not assume that screenshots from different engines will be pixel-identical.
Viewport and device scale
Set the viewport before navigation or capture to control the CSS layout width and height. To make a higher pixel-density image, set deviceScaleFactor when creating the browser context:
const context = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
});
const page = await context.newPage();
A larger viewport changes responsive layout; a larger device scale factor increases output pixel dimensions and can increase file size and capture time. Use the same settings when generating visual baselines.
Wait for the page you actually need
page.goto() supports wait conditions including load, domcontentloaded and networkidle. A page may continue loading analytics or polling requests after it looks ready, so waiting for every network request to stop is not always appropriate. For a specific dynamic component, wait for its selector instead:
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('[data-report-ready="true"]').waitFor({ state: 'visible' });
await page.screenshot({ path: 'report.png', fullPage: true });
You can also wait a fixed duration for a known animation or delayed update, but a selector or application-ready condition is usually more dependable than an arbitrary delay. Set a suitable navigation timeout for slow sites. Disable animations in the screenshot call when transient animation would make the capture inconsistent.
5. Capture an element or control the page first
Locator APIs let you interact with a page before capturing. For example, click a button to reveal a panel, then capture that panel:
await page.getByRole('button', { name: 'Show details' }).click();
const panel = page.locator('#details');
await panel.waitFor({ state: 'visible' });
await panel.screenshot({ path: 'details.png' });
For reproducible captures, consider whether the page needs a known viewport, authentication state, cookies, locale or timezone. Playwright browser contexts can be configured before opening the page. Be careful with secrets: do not commit credentials or authenticated browser state to source control.
6. Cross-browser and visual comparison notes
Playwright can automate Chromium, Firefox and WebKit; install the browsers you intend to use. A screenshot from one engine is not proof that another engine renders the same layout. If a screenshot is a visual regression baseline, keep the browser version, Windows environment, viewport, device scale, fonts and headless settings consistent. Playwright notes that host OS, browser version, settings, hardware, power source and headless mode can all affect rendering. Its test runner provides expect(page).toHaveScreenshot() for screenshot comparisons. See Playwright visual comparisons.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Browser executable missing or launch fails immediately | The browser binary for this Playwright package version is not installed, or the package was upgraded. | Run npx playwright install chromium, or npx playwright install for all supported browsers. Confirm the command runs in the same project as the installed package. |
| Browser download fails on a company or campus network | A proxy or certificate inspection blocks the browser download. | In PowerShell, set $Env:HTTPS_PROXY="https://proxy.example:port" before running the installer. If the proxy uses a custom certificate, configure NODE_EXTRA_CA_CERTS with the trusted certificate path as described in the browser documentation. |
| Navigation times out | The site is slow, unreachable, or keeps background requests open while using a strict wait condition. | Check the URL and network access, increase the navigation timeout when appropriate, or wait for domcontentloaded and then wait for the specific content selector. |
| Screenshot is blank or missing below-the-fold content | The page was captured before it rendered, or the capture used viewport mode. | Wait for a visible content selector and set fullPage: true for the entire scrollable page. |
| Element screenshot fails or captures the wrong thing | The selector is absent, hidden, ambiguous or points to a different element. | Use a unique locator, wait for it to become visible, and inspect the page before capture. |
| Images or fonts are absent | External resources have not loaded, are blocked, or are lazy-loaded only after scrolling. | Wait for the relevant image or font-dependent element; for lazy content, scroll the page or element into view before capture. Check the browser console and network conditions if resources still fail. |
| Image differs from a local visual baseline | Browser, OS, font, viewport, device scale or rendering environment changed. | Generate and compare the baseline in a consistent environment, and update the baseline only after reviewing the intended change. |
8. Performance, reliability and cost
- Performance: Launching a browser for every URL adds startup overhead. For a batch in one process, reuse one browser and create a fresh page or context per capture as needed, then close them cleanly. Full-page screenshots of very long pages and high device scale factors need more memory and can take longer.
- Reliability: Use explicit timeouts, wait for meaningful page state, and close the browser in a
finallyblock. If a site behaves differently in headless mode, compare with a headed run while keeping the other settings fixed. A successful navigation does not guarantee that every third-party resource loaded. - Cost: This workflow runs on your own Windows machine or infrastructure. Budget for your machine, runtime environment and any network or hosted infrastructure you choose; the research materials do not establish a specific Playwright service price. Browser binaries take disk space, and installing only Chromium avoids downloading browsers you do not need.
- Privacy: The page is loaded by the browser environment you run. Treat screenshots, cookies, authenticated pages and saved browser state as potentially sensitive files.
Or skip the browser setup
If you only need a screenshot and do not want to install or maintain browser binaries, ScreenshotNeo provides a website screenshot API and MCP server. One GET request returns an image or PDF; the example below saves a WebP screenshot. See the ScreenshotNeo API docs for options and configuration.
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 and consent banners 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 and failed loads are never billed, and response headers report the page verdict and billing status. Its MCP server lets AI agents use screenshot, page-info and PDF-capture tools. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.
FAQ
Does the India location change the Playwright setup?
No India-specific setup is documented in the sources used here. Use the supported Node.js and Windows versions, and account for your own network or proxy settings if browser downloads are restricted.
Can I capture a page without saving directly to disk?
Yes. Omit path from page.screenshot() to receive the screenshot bytes as a buffer, which you can pass to another part of your Node.js program.
Does full-page mode include content that loads only after scrolling?
Full-page mode captures the page’s scrollable area, but sites may defer loading some images or sections until they are scrolled into view. Scroll or wait for those elements before taking the screenshot when needed.


