Skip to Content
Deployment & OperationsScreenshot Best Practices

Screenshot Best Practices

Capture stable, reproducible browser screenshots across headless and headful environments.


Prerequisites

  • BotBrowser installed and running. See Installation Guide.
  • A profile file (.enc for production).
  • Playwright or Puppeteer installed for programmatic screenshots.
  • On Linux: A virtual display (Xvfb) must be running. See Headless Server Setup.

Quick Start

Playwright

import { chromium } from "playwright-core"; const browser = await chromium.launch({ executablePath: process.env.BOTBROWSER_EXEC_PATH, headless: true, args: [ `--bot-profile=${process.env.BOT_PROFILE_PATH}`, ], }); const page = await browser.newPage(); await page.goto("https://example.com"); // Viewport screenshot await page.screenshot({ path: "viewport.png" }); // Full page screenshot await page.screenshot({ path: "fullpage.png", fullPage: true }); await browser.close();

Puppeteer

import puppeteer from "puppeteer-core"; const browser = await puppeteer.launch({ executablePath: process.env.BOTBROWSER_EXEC_PATH, headless: true, defaultViewport: null, args: [ `--bot-profile=${process.env.BOT_PROFILE_PATH}`, ], }); const page = await browser.newPage(); await page.goto("https://example.com"); // Viewport screenshot await page.screenshot({ path: "viewport.png" }); // Full page screenshot await page.screenshot({ path: "fullpage.png", fullPage: true }); await browser.close();

How It Works

Screenshots in BotBrowser use the same rendering pipeline as a regular Chrome installation, with fingerprint properties applied from the profile:

  1. Resolution and DPI. The profile defines screen dimensions and device pixel ratio (DPR). A profile with DPR 2 produces screenshots at 2x the viewport pixel dimensions. In Puppeteer, always set defaultViewport: null so Puppeteer does not override the profile’s display settings. In Playwright, do not set explicit viewport dimensions in context options.

  2. Viewport vs. full page. A viewport screenshot captures only the visible area. A full page screenshot scrolls the entire page and stitches the result. The viewport dimensions come from the profile.

  3. Rendering consistency. Canvas noise, font rendering, and WebGL output are all determined by the profile. Screenshots taken with the same profile produce identical visual output across different host systems.

  4. Headless Linux. On servers without a monitor, Xvfb provides the virtual display that Chrome’s compositor needs. Without it, screenshots time out or produce blank images.


Common Scenarios

Correct screenshot order

When taking both viewport and full page screenshots, capture the full page screenshot first or wait between captures. Taking a viewport screenshot immediately followed by a full page screenshot in rapid succession can cause rendering issues:

// Recommended: wait for the page to stabilize await page.goto("https://example.com", { waitUntil: "networkidle" }); // Take viewport screenshot await page.screenshot({ path: "viewport.png" }); // Wait briefly before full page capture await page.waitForTimeout(500); await page.screenshot({ path: "fullpage.png", fullPage: true });

PNG vs. JPEG format

// PNG: lossless, larger files, better for text-heavy pages await page.screenshot({ path: "output.png", type: "png" }); // JPEG: lossy, smaller files, configurable quality await page.screenshot({ path: "output.jpg", type: "jpeg", quality: 80 });

Use PNG when pixel accuracy matters (fingerprint verification, visual regression testing). Use JPEG for general-purpose captures where file size is a concern.

High-DPI screenshots

The screenshot resolution is determined by the profile’s device pixel ratio. A profile with devicePixelRatio: 2 on a 1920x1080 viewport produces a 3840x2160 screenshot:

// The profile controls DPI. No additional configuration needed. await page.screenshot({ path: "hidpi.png" });

To override the profile’s DPI for a specific use case:

chromium-browser \ --bot-profile="/path/to/profile.enc" \ --bot-config-disable-device-scale-factor=true

Screenshots on headless Linux

Ensure Xvfb is running with a resolution at least as large as the profile’s screen dimensions:

# Start Xvfb with sufficient resolution Xvfb :10 -screen 0 2560x1440x24 -ac & export DISPLAY=:10.0 # Launch BotBrowser chromium-browser \ --headless \ --no-sandbox \ --bot-profile="/path/to/profile.enc" \ --remote-debugging-port=9222

If the Xvfb resolution is smaller than the profile’s screen size, screenshots may be clipped or produce unexpected results.

Element-specific screenshots

// Playwright const element = await page.locator("#target-element"); await element.screenshot({ path: "element.png" }); // Puppeteer const element = await page.$("#target-element"); await element.screenshot({ path: "element.png" });

Troubleshooting / FAQ

ProblemSolution
Screenshot times out on LinuxEnsure Xvfb is running and DISPLAY=:10.0 is set. See Headless Server Setup.
Blank or all-white screenshotThe page may not have finished loading. Use waitUntil: "networkidle" or wait for a specific element.
Screenshot resolution is wrongIn Puppeteer, set defaultViewport: null to let the profile control dimensions. In Playwright, do not set explicit viewport options.
Full page screenshot crashesAvoid capturing viewport and full page screenshots in rapid succession. Add a brief wait between them.
Fonts look different than expectedBotBrowser uses the profile’s embedded font bundle. Verify the profile matches your expected platform (Windows, macOS, etc.).
Colors appear different across runsThis is expected. Canvas noise produces deterministic but session-unique visual output. Use the same profile and noise seed for identical results.

Next Steps


Related documentation: Advanced Features | Installation Guide


Legal Disclaimer & Terms of Use Responsible Use Guidelines . BotBrowser is for authorized fingerprint protection and privacy research only.