How to Make an AI Agent Screenshot a Webpage at a Fixed Browser Window Size
Set a fixed Playwright viewport before navigation, capture predictable page dimensions, and learn when full-page screenshots or a screenshot API fit better.
To make an AI agent screenshot a webpage at a fixed size, set the page viewport before navigating, then take a normal viewport screenshot. For example, a 1280 × 720 viewport produces an image at those dimensions when using CSS-pixel screenshot scale. In Playwright, the viewport is the webpage’s layout area; it is not the outer desktop browser window with tabs and toolbar.
1. Fix the page viewport with Playwright
Install Playwright and its Chromium browser, then run this complete Node.js example. It sets the viewport before navigation, waits for the page’s load event, and saves the visible viewport as a PNG.
npm install playwright
npx playwright install chromium
import { chromium } from 'playwright';
const browser = await chromium.launch();
try {
const page = await browser.newPage({
viewport: { width: 1280, height: 720 },
deviceScaleFactor: 1,
});
await page.goto('https://example.com', { waitUntil: 'load' });
await page.screenshot({ path: 'page.png', scale: 'css' });
} finally {
await browser.close();
}
The width and height values are CSS pixels. A regular page.screenshot() captures the currently visible viewport. Set the viewport before navigation because responsive sites may choose a layout or load assets based on the page dimensions. Playwright recommends this order in its viewport documentation.
Configure one viewport for several pages
If the agent opens several pages in one browser context, set the viewport on the context. Pages created in that context inherit its settings:
import { chromium } from 'playwright';
const browser = await chromium.launch();
try {
const context = await browser.newContext({
viewport: { width: 1280, height: 720 },
deviceScaleFactor: 1,
});
const page = await context.newPage();
await page.goto('https://example.com', { waitUntil: 'load' });
await page.screenshot({ path: 'page.png', scale: 'css' });
} finally {
await browser.close();
}
Use page.setViewportSize({ width, height }) when changing a single page’s size after creating it. Set it before goto() when possible. Playwright notes that changing a page viewport also resets its screen size; if both screen and viewport dimensions matter, configure them on the browser context.
Python example
For a Python agent, install the async API and Chromium, then create the page with its viewport:
pip install playwright
playwright install chromium
import asyncio
from playwright.async_api import async_playwright
async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
try:
page = await browser.new_page(
viewport={"width": 1280, "height": 720},
device_scale_factor=1,
)
await page.goto("https://example.com", wait_until="load")
await page.screenshot(path="page.png", scale="css")
finally:
await browser.close()
asyncio.run(main())
Puppeteer alternative
If the agent already uses Puppeteer, set the page viewport before navigation:
npm install puppeteer
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
try {
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 720, deviceScaleFactor: 1 });
await page.goto('https://example.com', { waitUntil: 'load' });
await page.screenshot({ path: 'page.png' });
} finally {
await browser.close();
}
Puppeteer’s viewport API likewise recommends setting dimensions before navigation when a site responds to viewport changes. Some mobile or touch configurations can cause a reload when the viewport is changed.
2. Choose the screenshot dimensions and capture mode
| Setting | What it controls | Use it when |
|---|---|---|
viewport.width / viewport.height |
The webpage’s layout area in CSS pixels | You need a fixed visible browser page area, such as 1280 × 720 |
deviceScaleFactor |
Device pixel ratio used by the page | You need consistent high-density rendering; use 1 for a straightforward one-to-one setup |
scale: 'css' |
Playwright screenshot output uses CSS-pixel scale | You want predictable image dimensions tied to the CSS viewport |
fullPage: true |
Captures the full scrollable document | You need the entire page; the resulting image will be taller than the viewport |
| Element screenshot | Captures a selected element’s bounds | You need a chart, card, or other specific region |
For an exact viewport-sized artifact, leave fullPage off. To capture the entire document instead, explicitly use await page.screenshot({ path: 'whole-page.png', fullPage: true }). Playwright documents viewport, full-page, and element screenshots in its screenshots guide.
Screenshot scale affects pixel output. Playwright’s css scale produces one image pixel per CSS pixel; device scale uses device pixels and can produce a larger image on a high-density context. Keep viewport, device scale factor, and screenshot scale the same across runs when dimensions matter.
3. Make agent captures repeatable
A fixed viewport controls responsive layout, but it does not make every screenshot pixel-identical across machines. Browser version, operating system, fonts, rendering settings, hardware, and headless mode can affect output. For visual comparisons, keep the browser version, operating environment, and capture settings stable, as Playwright’s visual comparisons guidance explains.
- Wait for the right page state. The example waits for
load. For a single-page application or delayed content, wait for a meaningful selector or a short, justified delay before capturing. A load event alone may not mean that client-rendered content is ready. - Keep scale settings explicit. Set
deviceScaleFactorand screenshotscaleso a machine default does not change output size. - Use one browser context per task. Context-level viewport settings make batches consistent and isolate cookies and page state between tasks when using separate contexts.
- Decide how to handle animation and changing content. A live clock, rotating banner, animation, or personalized page can differ between captures even at identical dimensions. Where appropriate, disable animation or hide the changing element with a screenshot style or CSS.
- Check the actual file dimensions. Confirm the saved image is 1280 × 720 when exact output dimensions are a requirement. If it is larger, inspect screenshot scale, device scale factor, and whether full-page capture was enabled.
4. Know when a viewport is not a browser window
Playwright and Puppeteer viewport APIs size the webpage’s layout area. They do not set the literal operating-system window size including browser tabs, address bar, and toolbar. If an agent needs a screenshot of that outer desktop window, it needs a host-level window or desktop capture method; page screenshot APIs do not capture browser chrome.
A viewport is also not the same as a physical device. A desktop viewport can trigger responsive breakpoints, but mobile emulation may involve additional device, touch, and user-agent settings. Choose the dimensions and emulation settings that match the layout the agent is meant to inspect.
5. Or skip the browser setup
If the goal is a webpage image at a chosen viewport size, ScreenshotNeo provides a screenshot API and MCP server. Its API documentation describes the available parameters. Here is a cURL request; replace the API key and target URL, and set the viewport parameters as documented:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-d width=1280 \
-d height=720 \
-o shot.webp
The corresponding Python and Node.js requests use the same endpoint and viewport parameters:
import requests
params = {
"access_key": "YOUR_API_KEY",
"url": "https://example.com",
"width": 1280,
"height": 720,
}
r = requests.get("https://api.screenshotneo.com/v1/shot", params=params, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com',
width: '1280',
height: '720',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));
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 report the page verdict and billing status. Its MCP server gives AI agents the take_screenshot, get_page_info, and capture_pdf tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for the free plan.
6. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Image has unexpected dimensions | fullPage is enabled, device scale changes pixel dimensions, or the viewport differs from the requested size |
Disable full-page mode, set viewport and device scale explicitly, and use CSS screenshot scale. Check the saved file’s dimensions. |
| Page uses the wrong responsive layout | Viewport was set after navigation or a different device context is active | Create the page or context with the desired viewport before calling goto(). |
| Screenshot is blank or missing content | Capture happened before client-rendered content appeared, or navigation failed | Wait for the relevant selector or page state, check navigation errors, and confirm the URL is reachable from the agent’s environment. |
| Different pixels between runs | Browser, OS, fonts, headless mode, or dynamic page content changed | Pin and reuse the browser environment and settings; wait for content to settle and disable relevant animations or changing elements. |
| Playwright reports browser executable missing | The package is installed but its browser binary is not | Run npx playwright install chromium (or playwright install chromium for Python) in the deployment environment. |
| Mobile viewport change reloads a page | Some emulation settings can trigger a reload when viewport changes | Set the viewport and device settings before navigation, particularly with Puppeteer mobile or touch configurations. |
| Need tabs or address bar in the image | A page screenshot captures page content rather than browser chrome | Use a host-level desktop or window capture method. |
7. Performance, reliability, and cost
Browser automation requires a browser process and its supporting binaries in the agent’s runtime. Reuse a browser for multiple captures when practical, while creating contexts to control page state and apply consistent viewport settings. Large full-page images, high device scale factors, and heavy sites increase memory, transfer, and processing needs. Capture only the region and resolution the downstream task requires.
For reliability, always close the browser in a finally block, use a navigation or task timeout appropriate to the site, and treat navigation failures as failed captures instead of saving an ambiguous artifact. A fixed viewport improves layout consistency; it does not guarantee that a site is available or that its content is stable.
Playwright and Puppeteer are open-source automation libraries, but running them still uses your compute and may require maintaining browser binaries. A screenshot API avoids managing that browser setup and instead has the provider’s plan and request limits. ScreenshotNeo’s stated plans range from 1,000 free shots per month to paid tiers: 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; every feature is available on every plan. Compare the actual capture parameters and response behavior with your needs before switching.
8. FAQ
Does a 1280 × 720 viewport always produce a 1280 × 720 image?
With a normal viewport screenshot and CSS-pixel scale, that is the intended output. Full-page mode, device-pixel scaling, and other capture settings can change the image dimensions.
Can I set the outer browser window to 1280 × 720 with Playwright?
The page viewport APIs set the webpage layout area, not the operating-system window including browser controls. Use host-level window capture if browser chrome must appear.
Should I use Playwright or Puppeteer?
Use the library already supported by the agent’s stack. Both provide page viewport settings and screenshots; the key is to set the dimensions before navigation and keep the capture settings stable.
Can a screenshot API return a full-page image too?
ScreenshotNeo supports full-page capture with lazy images loaded. Consult its parameter documentation for the current request options.


