ScreenshotNeo

BlogHow-to

Chrome Headless Screenshot Shows an Indian Website’s Mobile View

A mobile-looking screenshot can come from viewport emulation, responsive CSS, user-agent handling, or locale settings. Check each cause separately.

By the ScreenshotNeo team4 October 20268 min read

If a Chrome Headless screenshot of an Indian website looks like its mobile layout, first check the browser’s effective viewport and whether mobile device emulation or a mobile user agent is enabled. Then check the site’s responsive breakpoints, viewport metadata, redirects, and locale settings. The fact that a page shows India-specific content does not by itself mean Chrome is in mobile mode.

Diagnose the layout and the regional content as separate questions. A narrow CSS viewport can trigger a mobile layout; a site can also select country- or language-specific content while rendering a desktop layout.

1. Check Puppeteer’s viewport and device emulation

Puppeteer’s page.emulate(device) applies a device’s viewport metrics and user agent. Set it before navigation because emulation resizes the page. If you want a desktop capture, remove unintended device emulation and set an explicit desktop viewport before loading the URL. See the Puppeteer emulation documentation.

Minimal desktop capture in Puppeteer

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 1000, deviceScaleFactor: 1 });
  // Do not call page.emulate() with a phone descriptor for this capture.
  await page.goto('https://example.in/', { waitUntil: 'networkidle2' });

  const dimensions = await page.evaluate(() => ({
    innerWidth: window.innerWidth,
    innerHeight: window.innerHeight,
    devicePixelRatio: window.devicePixelRatio,
    userAgent: navigator.userAgent
  }));
  console.log(dimensions);
  await page.screenshot({ path: 'desktop.png', fullPage: true });
} finally {
  await browser.close();
}

Replace https://example.in/ with the target. The dimensions logged from inside the page are more useful than assuming the requested viewport survived unchanged. Also log your configured viewport and any device descriptor in the capture script.

Check mobile emulation explicitly

const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 1000, deviceScaleFactor: 1 });
// Search your code for calls like this; it intentionally enables a device profile.
// await page.emulate(puppeteer.KnownDevices['iPhone 13']);
await page.goto('https://example.in/', { waitUntil: 'networkidle2' });

Use the device profile only when you intend to test that device. A call to emulate can change both viewport metrics and the user agent. The device scale factor controls pixel density; by itself, it is not evidence that the CSS viewport is narrow.

2. Confirm the effective viewport and mobile behavior

Chrome’s device metrics can affect screen dimensions, inner dimensions, and CSS media queries involving device width and height. Its mobile emulation also enables behaviors such as viewport meta tag handling, overlay scrollbars, and text autosizing. Inspect the DevTools Protocol device metrics for the controls available in your Chrome and Puppeteer versions.

const state = await page.evaluate(() => ({
  innerWidth: window.innerWidth,
  innerHeight: window.innerHeight,
  screenWidth: window.screen.width,
  screenHeight: window.screen.height,
  devicePixelRatio: window.devicePixelRatio,
  viewportMeta: document.querySelector('meta[name="viewport"]')?.content ?? null
}));
console.log(state);

For a desktop capture, verify that innerWidth is the width you intended and inspect the viewport metadata. A page can also change its own layout after navigation through scripts, so compare values after the page has loaded.

3. Check responsive CSS and viewport metadata

A page can use mobile styling at a narrow width even in a desktop browser. Responsive design commonly keeps the same URL and HTML while CSS changes the presentation to suit the available screen size. Google’s mobile-first guidance describes responsive layouts and other mobile configurations. Inspect the page’s media queries and compare the screenshot at a known wide viewport.

The viewport meta tag also affects how a page is laid out on mobile devices. Check it alongside the actual viewport rather than treating the visual appearance as proof of a browser mode. Google documents the viewport meta tag.

// In DevTools or Puppeteer, inspect the page's viewport declaration:
const viewportTag = await page.$eval(
  'meta[name="viewport"]',
  element => element.getAttribute('content')
).catch(() => null);
console.log(viewportTag);

If the tag is absent, that is a site configuration to investigate; do not assume adding or changing it in your capture script is the right fix. First establish whether the target site is expected to be responsive and what viewport your test is supposed to represent.

4. Separate locale variation from the layout

A site may choose language, currency, or other regional content using a selected region, cookies, language preferences, URL, or perceived visitor location. That can happen independently of mobile emulation. Google describes these as locale-adaptive pages and notes that a page may return different content based on perceived country or preferred language.

Compare the requested URL and final URL, language headers, cookies, any region selector, and network egress location against a known reference. Google cautions that IP location analysis is difficult and generally not reliable as a way to adapt content; a country-specific result alone does not establish that IP location caused it. See Google’s multi-regional site guidance.

Also check whether the server varies its response by user agent or redirects mobile visitors to a separate URL. Record the destination after navigation:

await page.goto('https://example.in/', { waitUntil: 'networkidle2' });
console.log('Final URL:', page.url());

Compare that final URL and page content with a desktop user agent and a mobile user agent while keeping the viewport width controlled. This helps distinguish server-side selection from CSS responsive behavior.

5. Use a controlled comparison

  1. Capture the same requested URL with an explicit wide viewport, such as 1440 by 1000, and record the effective innerWidth, innerHeight, and device pixel ratio.
  2. Search the capture code for page.emulate(), device descriptors, viewport overrides, and user-agent overrides. Disable unintended mobile settings and compare again.
  3. Inspect the viewport meta tag and the CSS breakpoints that apply at the effective width.
  4. Record the requested URL and final URL. Check redirects and user-agent-specific serving.
  5. Compare locale signals: selected region, cookies, language preferences or headers, and network location.
  6. If mobile is the intended test, keep the mobile profile and document which viewport and device profile the result represents.

Change one variable at a time. If the page becomes desktop-looking when only the viewport changes, investigate responsive behavior. If the layout stays the same but language, currency, or content changes with locale signals, investigate regional selection separately.

6. Troubleshooting common outcomes

Symptom Likely cause What to check or change
The logged innerWidth is narrow A phone device profile, viewport override, or later metric change is active. Remove unintended emulation; set the desktop viewport before navigation; inspect the effective dimensions after load.
Viewport is wide but content still looks mobile Site CSS, page scripts, or a user-agent-specific response may select a mobile presentation. Inspect media queries and the user agent; compare the final URL and response under controlled settings.
Layout is desktop but the page shows India-specific content Locale, language, cookies, selected region, URL, or network location may affect content. Compare those locale signals independently from viewport and device emulation.
The requested URL differs from the captured URL A redirect or site routing rule selected another destination. Log page.url() after navigation and compare with the same URL under another user agent.
Changing device scale factor does not fix the layout Pixel density is not the same as CSS viewport width. Check innerWidth and device metrics; adjust the viewport or emulation setting that actually controls layout.
Capture code says desktop, but screenshot is still narrow Another helper, wrapper, or later call may set device metrics or emulate a device. Search the full call path for viewport, device, and user-agent settings; log effective page values after navigation.

7. Performance, reliability, and cost considerations

For repeatable visual checks, make viewport, device profile, user agent, URL, locale signals, and wait condition explicit inputs. Record them with each capture so a later comparison can reproduce the same conditions. Avoid changing several inputs at once: it makes the source of a layout or content change harder to identify.

Choose a page readiness condition that matches the site. Waiting for network idle can be unsuitable for pages with ongoing requests; waiting for a known selector or a deliberate delay may better match the content being captured. Puppeteer and Chrome behavior can differ by installed version, so check the versions in your environment when API behavior does not match expectations.

For a recurring capture workflow, browser execution and retries consume your own compute and time. Set a bounded timeout, record failed navigations separately from valid screenshots, and avoid retrying a deterministic bad URL indefinitely. There is no universal cost or speed figure for this diagnosis; it depends on your browser environment and target pages.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. For one-off captures, it avoids maintaining the browser setup above. Its clean capture flow accepts cookie or consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response reports the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents.

For this particular issue, still specify the viewport you want and compare the result with your own browser capture. ScreenshotNeo supports device presets and custom viewports. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.in/ \
  -d width=1440 \
  -d height=1000 \
  -o shot.webp

The endpoint accepts a URL and returns an image or PDF. The basic request below uses the documented URL and access key parameters; add viewport settings according to the API documentation when you need to control the capture dimensions.

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.in/"},
    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.in/'
});
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', res);

Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed; an MCP server lets AI agents take screenshots; and 1,000 screenshots per month are free with no card. Paid plans start at $5 for 3,000 screenshots. Sign up free and capture 1,000 screenshots a month with no card.

FAQ

Does India-specific content prove the browser is using mobile mode?

No. Locale and layout are separate. A region or language choice can change content while the page remains at a desktop viewport.

Can a desktop browser show a mobile layout?

Yes. Responsive CSS can select a narrow layout based on viewport width, and user-agent handling can affect what the server returns.

Should I change the device scale factor to fix a narrow layout?

Usually, investigate viewport width and mobile emulation first. Device scale factor concerns pixel density and does not by itself establish the CSS viewport width.

Should I force the site to English to get its desktop layout?

Not as a first step. Change one input at a time and verify whether language or region affects content separately from the viewport and user agent.