How to Set the Viewport for Consistent Product Price Screenshots
Set a fixed browser viewport, device scale, and screenshot mode to make product price captures comparable. Get runnable Playwright examples and fixes for common inconsistencies.
To make product price screenshots consistent, set the same explicit viewport width and height for every capture, and keep the browser, device scale factor, screenshot scale, and execution environment stable. Choose dimensions that show both the price and enough product context to identify the item. There is no single correct viewport size for every retailer or use case.
This guide uses Playwright for runnable examples. The same principle applies to other browser automation tools: make the page viewport explicit, decide whether you need a viewport or full-page image, and keep the rest of the rendering setup consistent. See the Playwright emulation documentation, screenshot documentation, and visual comparison guidance.
1. Decide what the screenshot needs to show
Before choosing dimensions, identify the minimum useful frame. For a price record, that usually means the price and enough nearby product information to tell which item and variant it belongs to. If the price is below the fold, a viewport screenshot at the initial scroll position will not include it; scroll to the relevant section or capture the full page.
Use a fixed viewport for repeat captures. A viewport is the browser’s page area in CSS pixels; it is not the same thing as the final image’s pixel dimensions. Pick width and height based on the site layout and the information to preserve. Playwright’s documentation shows 1280 × 720 as an example configuration, not as a product-price standard.
2. Set a fixed viewport in Playwright
Install Playwright and its Chromium browser in a Node.js project:
npm install playwright
npx playwright install chromium
Save this as capture-price.cjs. It opens a product page at a fixed viewport, waits for the page to load, optionally scrolls to a price selector, and saves a viewport screenshot.
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
viewport: { width: 1280, height: 900 },
deviceScaleFactor: 1,
});
const page = await context.newPage();
try {
await page.goto('https://example.com/product', {
waitUntil: 'domcontentloaded',
timeout: 30000,
});
// If the price is below the initial viewport, bring it into view.
const price = page.locator('[data-testid="price"]').first();
if (await price.count()) {
await price.scrollIntoViewIfNeeded();
}
await page.screenshot({
path: 'product-price.png',
fullPage: false,
animations: 'disabled',
});
} finally {
await browser.close();
}
})();
Replace the example URL and selector with the target page and a selector that exists on it. If the page does not expose a stable price selector, remove the selector block and choose a viewport and scroll position that frame the price reliably.
Configure the browser context once
When capturing multiple product pages in the same run, create the context with the shared viewport and device scale factor, then open each page from that context. This avoids accidental differences caused by per-page defaults.
const context = await browser.newContext({
viewport: { width: 1280, height: 900 },
deviceScaleFactor: 1,
});
for (const url of productUrls) {
const page = await context.newPage();
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: makeFilename(url), fullPage: false });
await page.close();
}
3. Keep viewport, device scale, and image scale straight
| Setting | What it controls | How to keep captures comparable |
|---|---|---|
| Viewport width and height | The page layout area in CSS pixels, which affects responsive breakpoints and what is visible. | Set both values explicitly and reuse them. |
| Device scale factor | Emulated device pixel density. It is separate from viewport dimensions. | Set it explicitly in the browser context; do not rely on defaults. |
| Screenshot scale | How CSS pixels map to output image pixels. Playwright supports CSS-pixel and device-pixel output scales. | Choose one output scale and use it for every capture. |
| Screenshot mode | Whether the image shows the current viewport or the entire scrollable page. | Use the same mode and scroll position for the same comparison. |
| Browser and environment | Fonts, rendering, layout, and other visual details can vary across browser versions, operating systems, hardware, and headless settings. | Use the same browser version and execution environment as the baseline where possible. |
For example, a 1280 × 900 CSS-pixel viewport with a device scale factor of 2 can produce a different output pixel size from the same viewport at scale factor 1. A larger raster does not mean the page used a larger CSS viewport. Playwright documents the distinction between CSS and device screenshot scales in its screenshot options.
Choose viewport-only or full-page capture
A viewport screenshot captures the currently visible page area. A full-page screenshot extends the image to include the scrollable page. Full-page mode can be useful when prices or product context are spread down a page, but it changes image framing and dimensions. Use viewport-only captures when a stable, comparable frame is the goal; use full-page when the complete page is necessary, and keep that choice fixed across the set.
4. Use Python or cURL when you need a ScreenshotNeo capture
For an automated screenshot through an API, ScreenshotNeo accepts a URL in one GET request and can return PNG, JPEG, WebP, or PDF. Its viewport options let you request consistent dimensions without managing a browser installation. See the ScreenshotNeo API documentation for the available parameters and output formats.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://stripe.com'
});
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()));
To request a particular viewport, output type, or other capture behavior, use the corresponding API parameters documented in the ScreenshotNeo docs. Save the requested dimensions and relevant settings alongside the result if you compare captures over time.
5. Make repeated captures comparable
- Fix the target framing. Confirm that the price and identifying product context fit at the chosen viewport and scroll position.
- Set width and height explicitly. Reuse the same CSS-pixel dimensions for all captures in the comparison.
- Set device scale and screenshot output scale. Treat these as separate settings and record both.
- Keep the capture mode stable. Do not mix viewport-only and full-page images in one visual comparison.
- Pin the rendering environment. Use the same browser build, operating system or container, browser settings, and headless mode where possible.
- Wait for meaningful content. Prefer a relevant selector or a known page-ready condition when the page loads product data asynchronously. A fixed delay may be less reliable because load times vary.
- Record capture metadata. Store viewport, device scale factor, screenshot scale, browser and version, capture mode, and capture date with the image or its metadata. This is a practical record-keeping recommendation based on settings that affect output.
Viewport matching alone cannot guarantee pixel-identical rendering. Playwright’s guidance says, “For consistent screenshots, run tests in the same environment where the baseline screenshots were generated.” Rendering can vary with host OS, browser version, settings, hardware, power source, and headless mode. See the Playwright visual comparison documentation.
6. Handle dynamic pages and edge cases
Responsive layouts
A small viewport change can cross a responsive breakpoint and rearrange the product page. Keep the exact width stable; even nearby widths can produce a different column layout, move the price, or alter text wrapping.
Prices below the fold
Set a viewport tall enough for the desired frame or scroll the price into view before capturing. If you need the surrounding product details too, verify that scrolling does not push the identifying context out of the image.
Lazy-loaded content
Some product content appears only after scrolling or after client-side data loads. Wait for a relevant element to become visible before capture. For a full-page image, make sure lazy-loaded sections have had a chance to load; otherwise, the image can include placeholders or missing content.
Cookie banners and overlays
A consent banner, newsletter dialog, or chat bubble can obscure a price even with a stable viewport. Handle the site’s consent flow appropriately or use capture options that remove supported overlays. Do not change viewport dimensions to work around an overlay, since that can change the responsive layout too.
Product variants and changing prices
A size, color, location, currency, or subscription selection can change the displayed price. Keep the selection and any required cookies or headers consistent, and include the selected variant in the surrounding frame when it matters.
Fonts, animation, and personalization
Font loading, animations, rotating promotions, and personalized content can change layout or pixels between captures. Wait for the needed content, disable animations where the capture tool supports it, and keep locale, timezone, authentication state, and other relevant page state consistent.
7. Troubleshooting inconsistent screenshots
| Symptom | Likely cause | Fix |
|---|---|---|
| The price moves or the page layout changes. | Viewport dimensions differ or a responsive breakpoint was crossed. | Set identical width and height values explicitly and reuse them for every capture. |
| One screenshot is sharper or has different pixel dimensions. | Device scale factor or screenshot output scale differs. | Set both values explicitly; compare CSS viewport dimensions separately from output image dimensions. |
| The price is missing from the image. | It is below the fold, not loaded yet, or hidden by an overlay. | Wait for the price element, scroll it into view, or choose a suitable viewport height; resolve overlays without changing the viewport. |
| Full-page images do not align with viewport images. | The capture modes have different framing and page height. | Use a consistent mode for comparisons and note the mode in metadata. |
| Captures differ despite matching dimensions. | Browser version, OS, fonts, headless mode, hardware, dynamic content, or page state differs. | Use the same environment and browser build; stabilize page state and wait for required content. |
| Content is blank or incomplete. | The page is still loading, the target selector changed, or an asynchronous request failed. | Check navigation and console/network errors; wait for a stable page-specific selector and confirm it exists before capture. |
| A full-page screenshot misses images or sections. | Lazy-loaded content has not been triggered or finished loading. | Scroll through the page or wait for the relevant images and sections before full-page capture. |
8. Performance, reliability, and cost
For local Playwright captures, browser startup and page loading are usually part of each job’s runtime. Reusing a browser process and a configured context across a batch can avoid repeated startup overhead, while separate contexts help isolate cookies and page state. Keep timeouts bounded and wait for the specific content needed instead of adding a long fixed sleep to every capture.
For repeatable visual comparisons, a pinned environment improves reliability more than increasing screenshot resolution. Device-scale output creates larger images and can increase transfer and storage needs; use it only when high-density pixels are useful to the downstream workflow. Full-page images can also be much taller than viewport images.
ScreenshotNeo bills only clean shots: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Responses include X-Page-Verdict and X-Billed headers so you can see the page verdict and billing status. Plans are Free with 1,000 screenshots/month and no card, Starter at $5 for 3,000, Growth at $15 for 15,000, Pro at $39 for 60,000, Scale at $99 for 250,000, and Business at $249 for 1,000,000; yearly billing gives two months free, and every feature is on every plan. Check the API docs for configuration details before wiring captures into a recurring job.
Or skip the browser setup
ScreenshotNeo takes a screenshot from one API call, with viewport options documented in the API docs:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie banners are accepted like a visitor and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000.
Sign up free and capture your first 1,000 screenshots a month without a card.
FAQ
Is 1280 × 720 the best viewport for price screenshots?
No universal size is prescribed. It is an example viewport in Playwright documentation; choose dimensions that show the price and necessary product context on the page you capture.
Does the same viewport guarantee identical screenshots?
No. Browser version, operating system, fonts, hardware, headless settings, and dynamic page content can still affect rendering.
Should I use full-page screenshots to capture prices?
Only when the full page is needed. If the goal is a comparable record of a particular price area, a stable viewport and scroll position often provide a more consistent frame.
Are viewport size and device scale factor the same setting?
No. The viewport sets page dimensions in CSS pixels; device scale factor controls emulated pixel density, and screenshot scale determines output pixel mapping.


