Emulate a Mobile Device in Puppeteer and Capture a Screenshot – Step‑by‑Step Guide
Learn how to use Puppeteer’s Page.emulate to render a page exactly as it would appear on a mobile device, then take a screenshot. The guide covers prerequisites, a sample script, validation checks, and recovery options for CI environments.
09 Jan 2026, 02:45 UTC

Desired Outcome
Render a web page as it would appear on a specific mobile device, capture a screenshot, and verify that the viewport, user‑agent, and touch settings match the device descriptor. This is useful for visual regression testing, responsive design validation, or automated UI checks in continuous‑integration pipelines.
Prerequisites
- Node.js 18+ (LTS) installed on the host machine.
- npm or yarn package manager.
- Basic familiarity with JavaScript and command‑line operations.
- Access to a repository or project where you can add a new script file.
- Optional: A CI runner (GitHub Actions, GitLab CI, Jenkins) with Docker support for headless browsers.
Setup
Initialize a fresh npm project or use an existing one. In the project root, run:
npm init -y
npm install puppeteer@latest
We pin to the latest stable release to ensure the device descriptors list is current. If you prefer a specific version, adjust the version specifier accordingly.
Focused Procedure
- Create the script file – name it
mobile-screenshot.js.const puppeteer = require('puppeteer'); const path = require('path'); (async () => { // 1. Launch browser const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] // required in many CI containers }); // 2. Create a new page const page = await browser.newPage(); // 3. Choose a device descriptor const device = puppeteer.devices['iPhone X']; // replace with desired device // 4. Apply the device settings await page.emulate(device); // 5. Navigate to the target URL const targetUrl = 'https://example.com'; // placeholder await page.goto(targetUrl, { waitUntil: 'networkidle2' }); // 6. Optional: wait for a specific selector to ensure dynamic content is loaded // await page.waitForSelector('#main-content'); // 7. Capture screenshot const screenshotPath = path.resolve(__dirname, 'screenshots', `example-${device.name}.png`); await page.screenshot({ path: screenshotPath, fullPage: true }); console.log(`Screenshot saved to ${screenshotPath}`); // 8. Verify user‑agent matches the descriptor const ua = await page.evaluate(() => navigator.userAgent); console.log(`User‑Agent: ${ua}`); await browser.close(); })(); - Run the script – execute from the command line:
node mobile-screenshot.jsEnsure the
screenshotsdirectory exists or the script will throw an error. You can create it withmkdir -p screenshots. - Validate the output – open the PNG file and confirm its dimensions match the device’s viewport (e.g., 375x812 for iPhone X). Use an image viewer or
identify -format "%wx%h" screenshot.png(ImageMagick) for automated checks. - Optional: Diff against baseline – store a reference image and compare using
pixelmatchorjest-image-snapshotin a test harness.
Expected Checks
- Viewport size – The screenshot should match the device’s logical resolution. For iPhone X, expect 375x812 pixels.
- User‑agent string – The console log should contain the device’s user‑agent, e.g.,
Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X).... - Touch support – Inspect
page.isMobile()andpage.isTouch()if needed: they should returntrue. - Network idle – The
networkidle2option ensures the page has no more than two network connections for at least 500ms, indicating that most resources are loaded.
Recovery Options
- Timeouts – If the page hangs, increase the timeout in
page.gotoor replacenetworkidle2withload. - Sandbox errors in CI – Add
'--disable-setuid-sandbox'and'--no-sandbox'to the launch args. On Windows containers, use--disable-gpu. - Outdated device descriptors – Run
npm outdated puppeteerand update if the descriptor list is stale. A mismatch can cause incorrect viewport sizes. - Dynamic content – If the page relies on JavaScript timers, add
await page.waitForTimeout(2000)after navigation or wait for a specific DOM element.
Limitations
- Puppeteer’s device descriptors are static snapshots; they may not reflect the latest device models unless the library is updated.
- Headless Chrome may render certain CSS features slightly differently from a real device; visual regression tools should account for minor discrepancies.
- Network‑idle waits can be unreliable for pages that keep a WebSocket open; consider using
page.waitForFunction('document.readyState === "complete"').
Practical Verification Checklist
- Run the script and confirm the console logs the correct user‑agent.
- Open the PNG and verify dimensions.
- If you have a baseline image, run an image‑diff command:
pixelmatch screenshot.png baseline.png diff.png --threshold 0.1 - Review the diff image; any non‑zero diff indicates a visual regression.
Conclusion
By leveraging Page.emulate, you can reliably render a page as it would appear on any supported mobile device and capture a precise screenshot. This method is ideal for automated visual regression tests, responsive design validation, or CI‑driven UI checks. Remember to keep your Puppeteer version up‑to‑date, tailor the wait strategy to your page’s load behavior, and validate the output dimensions to ensure accuracy.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.