Getting pixel-identical screenshots from Chrome headless across Linux and Windows is tricky because font rendering, DPI scaling, and Chrome’s own defaults differ per OS. This guide gives you a repeatable setup — a set of flags, a fixed viewport, and a consistent environment — so the same command produces the same PNG on both systems.
What You’ll Need
- Chrome or Chromium installed on both machines (any recent stable version).
- Command-line access (Terminal on Linux, Command Prompt or PowerShell on Windows).
- Basic familiarity with running commands and editing a small script.
- Optional: a tool like
pngcheckor ImageMagick to verify output dimensions.
Step-by-Step
- Install the same Chrome version on both systems.
Version differences cause rendering changes. Use the same major version (e.g., both on Chrome 120) and ideally the same minor build. On Linux, you can pin a version viaaptor download the exact .deb; on Windows, use the offline installer for a specific version. - Set a fixed viewport size with
--window-size.
Chrome’s default window size differs by OS. Always pass--window-size=1280,720(or your desired size) to both. This includes the browser chrome, so add--hide-scrollbarsto avoid scrollbar width differences. - Disable GPU and hardware acceleration.
Use--disable-gpuon both. On Windows, also add--disable-software-rasterizerto prevent fallback rendering differences. - Force a consistent device scale factor.
Windows may apply DPI scaling (e.g., 125% or 150%). Add--force-device-scale-factor=1to both systems to ensure a 1:1 pixel mapping. - Use the same font rendering settings.
Linux uses fontconfig, Windows uses ClearType. To minimize differences, add--font-render-hinting=noneand--disable-lcd-texton both. This makes text rendering closer, though not always identical. - Set a common user agent and platform.
Websites may serve different CSS or images based on OS. Use--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"on both to emulate the same platform. - Disable features that cause variability.
Add--disable-extensions,--disable-default-apps,--disable-sync, and--no-first-run. These prevent popups, sync changes, and first-run dialogs from altering the page. - Use the same screenshot command.
On both systems, run:chrome --headless --disable-gpu --hide-scrollbars --force-device-scale-factor=1 --window-size=1280,720 --screenshot=output.png "https://example.com"
Adjust the path to your Chrome executable (e.g.,
chromeon Linux,"C:\Program Files\Google\Chrome\Application\chrome.exe"on Windows). - Wait for the page to fully load.
Headless Chrome captures the screenshot as soon as the page load event fires, but images and fonts may still be loading. Use the--virtual-time-budget=5000flag to give the page 5 seconds of virtual time to settle. This is crucial for consistent results. - Verify the output.
Check the file size and dimensions on both systems. They should be identical (or very close). Usefile output.pngon Linux oridentify output.png(ImageMagick) on Windows to confirm dimensions.
Common Mistakes
- Forgetting to set the same Chrome version. A patch update can change rendering.
- Not using
--hide-scrollbars. Windows scrollbars are always visible, Linux overlay scrollbars are not, causing width differences. - Using different viewport sizes. Even a 1-pixel difference shifts layout.
- Ignoring DPI scaling on Windows. Without
--force-device-scale-factor=1, a 125% scaling yields a 1600×900 screenshot instead of 1280×720. - Not waiting for fonts and images. Screenshots taken too early will have missing or fallback fonts.
Tips
- Use a shared script. Write a small shell/batch script that contains the full command and use it on both machines to avoid typos.
- Test with a simple page first. Create a local HTML file with known text and colors to verify consistency before testing complex sites.
- Consider using Docker. Running Chrome headless in a Docker container (e.g.,
chromiumimage) on both systems gives near-perfect consistency, as the environment is identical. - Use
--disable-features=CalculateNativeWinOcclusionon Windows. This prevents Windows-specific occlusion from affecting rendering. - If you need pixel-perfect, use a virtual machine. Even with all flags, minor font differences may persist. A Linux VM on Windows or vice versa can eliminate them.
Troubleshooting
- Screenshots are different sizes. Check that
--window-sizeand--force-device-scale-factor=1are present. Also, remove any--headless=newor--headless=oldvariations; use plain--headless. - Text looks blurry on one system. Ensure
--font-render-hinting=noneand--disable-lcd-textare used on both. If still blurry, try--disable-font-subpixel-positioning. - Page loads differently (e.g., cookie banners). Use
--disable-cookie-encryption? No, that’s not a real flag. Instead, use--user-data-dirto a fresh temp folder on both systems to ensure no saved preferences or cookies. - Screenshot is blank or white. The page may be blocking headless. Try adding
--disable-blink-features=AutomationControlledto make Chrome appear less automated. - Chrome won’t start on Linux as root. Add
--no-sandbox(only in a controlled environment) or run as a non-root user. - Images or fonts missing. Increase
--virtual-time-budgetto 10000 or more. Also check that the site doesn’t block based on user agent; your custom user agent should fix that.
Frequently Asked Questions
Why do my screenshots still differ slightly even with all flags?
Font rendering engines (fontconfig vs. ClearType) and subpixel positioning can cause sub-pixel differences. Using a Docker container is the most reliable way to achieve pixel-identical results.
Can I use Puppeteer or Selenium instead of command-line flags?
Yes, but you still need to set the same viewport, device scale factor, and user agent in your automation code. The flags in this guide are the underlying settings those tools use.
Does Chrome version really matter that much?
Yes. Chrome updates frequently change rendering, CSS support, and even default fonts. Using the same major version is essential; ideally, pin the exact build.
What if I need a full-page screenshot?
Full-page screenshots are harder to make consistent because the page height can vary. Use --screenshot with a fixed viewport for consistency; for full-page, you’ll need a tool like Puppeteer with a fixed width and capture beyond the viewport.
Is it better to use Chrome or Chromium?
Chromium is more minimal and may have fewer OS-specific integrations, but Chrome is fine. The key is to use the same binary on both systems.
Can I automate this for many URLs?
Yes, write a loop in your script that iterates over URLs, calling the same Chrome command each time. Ensure the output filenames are unique per URL.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- How to Cool Down an Overheating Laptop
- Good Password: How to Create One
- Remove Write Protection on External Hard Drive
- How to Disable Chkdsk at Windows Startup
- Restore WiFi and Secure Your Netgear Router After Reset
- Fix Error 0x80004005: Top Easy Ways That Work