ScreenshotNeo

BlogEngineering

Why Does My Web Page Screenshot Have a Different Font Size on Linux?

Linux does not automatically change CSS font sizes. Learn to separate CSS, font rendering, browser zoom, viewport, and screenshot scaling issues.

By the ScreenshotNeo team4 October 20269 min read

Linux does not inherently assign a different CSS font-size to a web page. Text can look larger or smaller in a screenshot because the screenshot maps CSS pixels to output pixels differently, browser zoom changes layout, a different font is selected or rendered, or the browser sees a different viewport or environment. Start by comparing computed styles and rendered fonts; then compare zoom, viewport, device scale factor, and screenshot scale.

This guide uses Playwright for a reproducible diagnosis. Its official documentation describes cross-platform rendering variation and the screenshot controls discussed below: Visual comparisons, Page screenshot options, and Browser context options.

1. First determine what “different font size” means

Separate three measurements that are easy to confuse:

  • CSS font size: the computed size in CSS pixels, such as 16px. Read it with getComputedStyle(element).fontSize.
  • Rendered glyph appearance: the font face, hinting, metrics, and rasterization used to draw the text. Two fonts at the same CSS size can have different apparent heights and widths.
  • Screenshot pixels: the raster image dimensions and scale. An image can contain more pixels per CSS pixel without the page’s CSS font size or layout changing.

If computed font-size differs between environments, investigate CSS rules, browser zoom, responsive breakpoints, user preferences, and page configuration. If it matches but letters look different or wrap differently, inspect the actual rendered font, webfont loading, font metrics, available line width, and screenshot scale.

2. Diagnose the page in both environments

Use the same target element in the Linux capture and the comparison environment. Run this in the page context after fonts have loaded and after the page has reached the state you intend to capture:

const selector = "h1";
await document.fonts.ready;
const el = document.querySelector(selector);
if (!el) throw new Error(`No element matches ${selector}`);
const style = getComputedStyle(el);
const rect = el.getBoundingClientRect();
console.log({
  fontSize: style.fontSize,
  fontFamily: style.fontFamily,
  fontWeight: style.fontWeight,
  lineHeight: style.lineHeight,
  letterSpacing: style.letterSpacing,
  width: rect.width,
  height: rect.height,
  viewport: { width: innerWidth, height: innerHeight },
  devicePixelRatio,
  fontsStatus: document.fonts.status
});

Also inspect the browser’s rendered-font information in developer tools. The computed font-family is the CSS list, not proof of which face supplied the glyphs. Confirm that the intended webfont loaded successfully and that the browser actually used it. A missing font may fall back to a local font with different glyph widths and vertical metrics.

Record these values on both systems:

  • Computed font-size, line-height, font weight, and bounding box.
  • Resolved/rendered font and webfont load status.
  • Viewport width and height before navigation, plus responsive breakpoint.
  • Browser zoom, browser and version, headless mode, and relevant user-agent.
  • window.devicePixelRatio, Playwright deviceScaleFactor, and screenshot scale.
  • Linux image/distribution and installed fonts when comparing CI with a workstation.

3. Make a reproducible Playwright capture

Set the viewport and device scale factor explicitly when creating the browser context, before navigating. Wait for fonts before taking the screenshot. The example below uses CSS-pixel screenshot output to make each image pixel correspond to one CSS pixel.

import { chromium } from "playwright";

const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
  viewport: { width: 1280, height: 800 },
  deviceScaleFactor: 1
});
const page = await context.newPage();
await page.goto("https://example.com", { waitUntil: "networkidle" });
await page.evaluate(() => document.fonts.ready);
console.log(await page.evaluate(() => ({
  viewport: [innerWidth, innerHeight],
  devicePixelRatio,
  heading: (() => {
    const el = document.querySelector("h1");
    if (!el) return null;
    const s = getComputedStyle(el);
    const r = el.getBoundingClientRect();
    return { fontSize: s.fontSize, fontFamily: s.fontFamily,
      lineHeight: s.lineHeight, width: r.width, height: r.height };
  })()
})));
await page.screenshot({ path: "linux.png", scale: "css" });
await browser.close();

Install Playwright and its Chromium browser in the project environment using the official Playwright installation guide. Replace https://example.com and the selector with your page and element. For a visual baseline intended to represent a particular device pixel ratio, set that factor explicitly and choose screenshot scale deliberately instead of relying on defaults.

Screenshot scale and device scale factor

Playwright’s screenshot scale can be "css" or "device". CSS scale yields one image pixel per CSS pixel; device scale yields one image pixel per device pixel. The documented screenshot default is "device". Browser contexts expose deviceScaleFactor, documented with a default of 1. A high-DPI context can therefore produce a screenshot with different pixel dimensions even if the CSS layout is unchanged.

Do not compare image dimensions as if they were CSS dimensions. For a like-for-like CSS-pixel comparison, use scale: "css" and align viewport and page state. If the goal is to reproduce a device-resolution capture, use scale: "device" with a matching, explicit device scale factor.

Browser zoom is a layout input

Chromium documents that browser zoom changes the size of a CSS pixel relative to a device-independent pixel and changes page layout. That can affect both apparent text size and responsive layout. Pinch zoom is different: it is applied after rendering and does not interact with layout. Screenshot output scale is another separate setting; changing it maps the rendered page to output pixels rather than changing CSS rules.

Fonts and Linux rendering

The same CSS font-family declaration can resolve differently on different machines. A webfont may fail to load, a requested family may not be installed, or a fallback may have different metrics. This can make glyphs seem larger at the same CSS size and can change line breaks, element heights, and page layout. Check the rendered font and network/font loading state before changing CSS. For pixel-level comparison, use the same OS image, browser build, and font set where possible, or maintain separate baselines for each platform.

Viewport, headless mode, and user agent

Viewport width can select a different responsive breakpoint and change available text width, wrapping, and surrounding layout. Set the viewport before navigation when the page responds to it. Playwright warns that rendering can vary with host OS, version, settings, hardware, power source, headless mode, and other factors.

Check device presets and custom user agents too. Playwright’s documented “Desktop Chrome” device preset uses a Windows-specific user-agent string. If the site uses user-agent-dependent CSS or server behavior, that preset may produce different output from Linux Chromium. Compare the actual viewport and user agent alongside the font measurements.

4. Use this decision sequence

  1. Compare computed CSS values. If font-size or line-height differs, inspect the cascade, zoom, media queries, user settings, and page state.
  2. Compare the element box and viewport. If width or height differs, check viewport, responsive breakpoint, wrapping, and content state.
  3. Compare the actual font. If CSS values match but glyphs differ, verify the rendered face and whether the intended webfont loaded; inspect fallback fonts and font metrics.
  4. Compare capture scale. Check device scale factor, devicePixelRatio, and screenshot scale. Normalize to CSS pixels if the goal is to compare CSS layout.
  5. Align the environment. Match browser/version, OS image, fonts, zoom, headless mode, viewport, and user agent as far as the use case permits.
  6. Keep platform-specific baselines when needed. Browsers and operating systems can render fonts differently. Separate baselines are often the right choice for pixel comparisons across platforms.

Avoid globally changing font sizes until these checks identify a real CSS discrepancy. A CSS adjustment can hide a scale or font-selection issue while introducing a genuine layout difference elsewhere.

5. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One request returns a PNG, JPEG, WebP, or PDF. For a Linux-friendly capture workflow, it removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, and failed loads are never billed; and its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Every feature is on every plan. See the API documentation for request options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));

Replace YOUR_API_KEY with your key. Use the screenshot options in the docs to set capture behavior explicitly, and compare the resulting page measurements if you are diagnosing a font discrepancy. Sign up for 1,000 free screenshots a month with no card.

6. Troubleshooting

Symptom Likely cause What to check or change
Text looks larger, but computed font-size matches Different rendered font, font metrics, or screenshot pixel mapping Inspect the rendered face, confirm webfont loading, and compare screenshot scale and device scale factor.
Computed font-size differs Zoom, cascade, responsive CSS, user preferences, or different page output Compare browser zoom, media queries, user settings, user agent, and computed styles at the same viewport.
Line wrapping differs while font size matches Different font metrics or available line width Compare rendered font, element width, viewport, breakpoint, letter spacing, and content.
Linux image has different pixel dimensions Device scale factor or screenshot scale differs Set deviceScaleFactor explicitly and choose scale: "css" or "device" based on the intended comparison.
Webfont is absent only in CI/Linux Font request failed, capture happened too early, or the page chose a fallback Inspect failed network requests and rendered-font information; wait for document.fonts.ready before capture.
Only one breakpoint differs Viewport or zoom changed the effective layout width Set viewport before navigation and verify the browser zoom and responsive rules.
Local and headless captures differ Headless mode or host environment changes rendering Align browser version, OS image, fonts, settings, and headless mode; keep baselines per environment if necessary.
Page differs despite a matching viewport User-agent-dependent output or timing/state differences Compare user agent, wait for fonts and page content, and ensure both captures use the same page state.

7. Performance, reliability, and cost

For stable, repeatable comparisons, pin the browser and host environment and avoid unnecessary variation in fonts, viewport, zoom, and headless mode. Waiting for document.fonts.ready helps prevent capturing before font loading settles; it does not prove that the intended face loaded, so also verify the rendered font and failed requests. Network-idle waits can be unsuitable for pages with ongoing requests; choose a readiness condition that matches the page you are capturing.

Screenshot scale affects output pixel dimensions and therefore the image being compared; it does not by itself establish that CSS font size changed. Browser zoom and viewport can change layout, so record them with the baseline. No prevalence statistic identifies one universal Linux cause: the exact diagnosis depends on the page, fonts, browser, capture configuration, and host environment.

With ScreenshotNeo, the stated billing rule is that only clean shots are billed: bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and each response identifies the page verdict and billing status in headers. Published tiers are Free: 1,000/month; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Yearly billing gives two months free. The product states that every feature is available on every plan; check the documentation for API parameters and response details.

8. FAQ

Does Linux change the CSS font-size property by itself?

No. Linux can affect font selection and rendering, while zoom, responsive rules, and capture configuration can affect layout or screenshot appearance. Check computed styles to determine whether the CSS value actually changed.

Should I use CSS scale or device scale for visual tests?

Use CSS scale when you want one output pixel per CSS pixel. Use device scale when the test is meant to represent device-pixel output, with the device scale factor set to match.

Should cross-platform pixel tests share one baseline?

Use a shared baseline only when the browser, OS, fonts, settings, and capture configuration are aligned closely enough for the comparison. Otherwise, keep platform-specific baselines.

Can I fix it by setting a larger CSS font size on Linux?

Only if computed styles show a real page-style difference that you intend to correct. If the cause is font metrics or output scaling, changing CSS can mask the diagnosis and alter layout.