ScreenshotNeo

BlogHow-to

How to Capture Responsive Website Screenshots at Desktop and Mobile Widths

Capture comparable desktop and mobile screenshots with Chrome DevTools or Playwright. Learn when to use viewport or full-page captures and how to automate both sizes.

By the ScreenshotNeo team4 October 20267 min read

To capture a responsive website at desktop and mobile widths, set the browser viewport to each target size and save a screenshot at each size. For a quick manual comparison, use Chrome DevTools’ Device Toolbar. For repeatable captures across pages or builds, use Playwright to set the viewport and save the images. Decide first whether you need only the visible viewport or the entire scrollable page; those produce different kinds of comparisons.

A browser-emulated mobile viewport is useful for checking responsive layout, but it is not the same as running the page on a physical phone. Chrome describes Device mode as a first-order approximation; verify on an actual device when mobile hardware behavior matters. Chrome DevTools documentation

1. Choose the capture scope and dimensions

Before capturing, record the viewport width and height, capture scope, device profile, and output scale. Keep those settings consistent when comparing desktop and mobile images. Otherwise, a difference may come from the capture setup rather than the responsive layout.

Goal Capture Why
Compare what visitors initially see Viewport screenshot Shows only the visible browser viewport at the selected size.
Review the whole page’s layout Full-page screenshot Includes content below the initial viewport; the result can be very tall.
Check a responsive breakpoint quickly One or more controlled widths Useful for seeing when columns, navigation, or spacing change.
Check behavior on actual mobile hardware Capture or inspect on a physical phone Emulation does not reproduce every mobile device characteristic.

There is no universally correct desktop or mobile dimension: choose sizes that represent the layouts you need to inspect. If you need comparable images for review, use the same height and capture scope where practical, and give each file a descriptive name such as landing-desktop-1440x900.png and landing-mobile-390x844.png.

2. Capture both widths with Chrome DevTools

  1. Open the page in Chrome and open DevTools.
  2. Toggle the Device Toolbar.
  3. Choose Responsive to enter custom width and height, or choose a device preset.
  4. Set the desktop dimensions and capture the page.
  5. Set the mobile dimensions and capture it again.
  6. From the Device Toolbar’s More options menu, choose Capture screenshot for the visible viewport or Capture a full size screenshot for the whole scrollable page.

Chrome’s device controls also include device type, pixel ratio, orientation, and device frame settings. Keep the relevant settings the same across captures unless one of them is the variable you are evaluating. See Simulate mobile devices with device mode for the current control details.

3. Automate desktop and mobile captures with Playwright

Playwright is useful when you need the same captures repeatedly, such as for several URLs or after each visual change. Install Playwright in a Node.js project with npm install -D playwright, then install a browser with npx playwright install chromium. Save the following as capture.mjs and run it with node capture.mjs https://example.com.

import { chromium } from 'playwright';

const url = process.argv[2];
if (!url) {
  throw new Error('Usage: node capture.mjs https://example.com');
}

const browser = await chromium.launch();
try {
  const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
  await page.goto(url, { waitUntil: 'load', timeout: 60_000 });
  await page.screenshot({ path: 'desktop-1440x900.png' });

  await page.setViewportSize({ width: 390, height: 844 });
  await page.screenshot({ path: 'mobile-390x844.png' });
} finally {
  await browser.close();
}

This saves viewport screenshots. To capture the full scrollable page, pass fullPage: true to the screenshot call, for example:

await page.screenshot({ path: 'mobile-full.png', fullPage: true });

For a device profile rather than a viewport alone, Playwright provides device descriptors. You can spread a descriptor into the page context and override its viewport for a particular capture:

import { chromium, devices } from 'playwright';

const browser = await chromium.launch();
try {
  const context = await browser.newContext({
    ...devices['Desktop Chrome'],
    viewport: { width: 1440, height: 900 },
  });
  const page = await context.newPage();
  await page.goto('https://example.com', { waitUntil: 'load' });
  await page.screenshot({ path: 'desktop.png' });
} finally {
  await browser.close();
}

Device descriptors can set characteristics such as user agent, screen size, viewport, and touch support. A viewport override lets you retain a profile while changing its dimensions. See Playwright’s Emulation guide and Screenshots guide.

Output scale, masking, and element captures

Playwright’s screenshot API accepts scale: 'css' for one output image pixel per CSS pixel, or scale: 'device' for device-pixel output. Device scale can create larger images. Choose deliberately when comparing or delivering captures. The API also supports masking selected elements when volatile regions should not dominate a visual comparison, and capturing a selected element instead of the page. Refer to the Page screenshot API for the supported options.

await page.screenshot({
  path: 'mobile-css-pixels.png',
  scale: 'css',
  mask: [page.locator('.dynamic-ad')],
});

await page.locator('main').screenshot({ path: 'main-element.png' });

Only use a mask when hiding that region is appropriate to the review; masking can conceal a real layout problem if applied carelessly.

4. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF; use the viewport parameters for desktop and mobile dimensions. The request below saves a WebP screenshot at a mobile viewport. See the ScreenshotNeo API documentation for available parameters, formats, and options.

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

Change width and height to the desktop viewport values and save to a separate file. ScreenshotNeo also accepts the parameter names used by other screenshot APIs, which can make switching easier.

import requests

params = {
    "access_key": "YOUR_API_KEY",
    "url": "https://example.com",
    "width": 390,
    "height": 844,
}
r = requests.get("https://api.screenshotneo.com/v1/shot", params=params, timeout=90)
r.raise_for_status()
with open("mobile.webp", "wb") as image:
    image.write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com',
  width: '390',
  height: '844',
});
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('mobile.webp', res);

Cookie and consent banners, newsletter popups, and chat widgets from more than 60 known platforms can be removed before capture, and each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status. Its MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.

5. Make captures comparable and reliable

  • Fix the viewport: record width and height for each capture and reuse them.
  • Fix the scope: do not compare a viewport image with a full-page image.
  • Fix the rendering profile: note device profile, pixel ratio, and screenshot scale when they matter.
  • Wait for meaningful content: if the page renders after load, use an explicit selector wait or a short, documented delay in your automation. Avoid an arbitrary long wait when a specific ready condition is available.
  • Account for dynamic areas: ads, timestamps, rotating banners, and personalized content can change between runs. Stabilize the page or mask only the regions that should be excluded.
  • Check actual devices when needed: screenshots from emulation do not prove that touch behavior, mobile browser chrome, or hardware-specific behavior works correctly.

Full-page captures are useful for document review but can be very tall, increasing file size and making side-by-side review harder. Viewport captures are usually a better fit for comparing the first screen at two widths. Device-pixel output can also increase dimensions and storage needs compared with CSS-pixel output.

6. Troubleshooting

Symptom Likely cause Fix
Desktop and mobile images look the same The viewport did not change, or the page has no responsive change at those widths. Confirm the width in DevTools or call setViewportSize before the second capture. Try widths on either side of a known layout breakpoint.
Screenshot is clipped below the fold The capture is viewport-only. Use DevTools’ full-size screenshot command or Playwright’s fullPage: true.
Mobile capture still looks like desktop A viewport was set without a mobile device profile, or the page itself does not adapt at that width. Set the intended viewport; if you need mobile emulation characteristics, use a Playwright device descriptor. Verify responsive behavior in the page and, if required, on a real phone.
Images, fonts, or client-rendered content are missing Capture began before that content was ready or a request failed. Wait for a meaningful selector or page-specific ready state before taking the screenshot, and inspect the page’s network and console errors.
Captures differ between runs without a code change Dynamic content, personalization, animation, or differing rendering settings. Keep the browser profile and viewport fixed, stabilize dynamic inputs where possible, and mask known volatile elements only when appropriate.
Playwright says the browser executable is missing The Playwright package is installed, but its browser was not installed. Run npx playwright install chromium for this example.
Large full-page output is slow or unwieldy The document is long or output uses device pixels. Use a viewport capture for above-the-fold review, or choose CSS-pixel scale where that resolution is sufficient.

7. FAQ

Should I use a device preset or a custom width?

Use a preset when its device characteristics are relevant to your check. Use a custom responsive viewport when the goal is to inspect a specific width or breakpoint. Playwright allows a viewport override on a device profile.

Does mobile emulation prove the page works on a phone?

No. Emulation is an approximation. Use an actual device for behavior that depends on mobile hardware or browser characteristics.

Should I save screenshots in CSS pixels or device pixels?

Use CSS-pixel scale for output aligned to CSS layout dimensions. Use device-pixel scale when you need the higher-resolution output; account for the larger image dimensions.

Can I automate many URLs and widths?

Yes. Put the desired URL and viewport combinations in data and loop over them in a Playwright script, using descriptive filenames that include the dimensions and capture scope.

Sources