Why Mobile Screenshots Matter

Over 60% of web traffic comes from mobile devices. If your site looks broken on a phone, you’re losing customers. Manual testing on every device is impractical — there are hundreds of screen sizes to consider.

Automated mobile screenshots let you verify responsive layouts at every breakpoint without touching a physical device.

Common Mobile Viewports

Here are the key viewport sizes to test:

DeviceWidthHeightScale
iPhone SE3756672x
iPhone 143908443x
iPhone 14 Pro Max4309323x
Samsung Galaxy S233607803x
iPad Mini76810242x
iPad Pro 12.9"102413662x

Basic Mobile Screenshot

Capture a screenshot at a mobile viewport using the ToolCenter:

const axios = require('axios');

async function mobileScreenshot(url, device = 'iphone14') {
  const devices = {
    iphone_se: { width: 375, height: 667, deviceScaleFactor: 2, mobile: true },
    iphone14: { width: 390, height: 844, deviceScaleFactor: 3, mobile: true },
    iphone14_max: { width: 430, height: 932, deviceScaleFactor: 3, mobile: true },
    galaxy_s23: { width: 360, height: 780, deviceScaleFactor: 3, mobile: true },
    ipad_mini: { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true },
    ipad_pro: { width: 1024, height: 1366, deviceScaleFactor: 2, mobile: true },
  };

  const config = devices[device] || devices.iphone14;

  const response = await axios.post(
    'https://api.toolcenter.dev/v1/screenshot',
    {
      url: url,
      width: config.width,
      height: config.height,
      deviceScaleFactor: config.deviceScaleFactor,
      mobile: config.mobile,
      format: 'png',
    },
    {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
      responseType: 'arraybuffer',
    }
  );

  return response.data;
}

Python Version

import requests

DEVICES = {
    'iphone_se': {'width': 375, 'height': 667, 'deviceScaleFactor': 2, 'mobile': True},
    'iphone14': {'width': 390, 'height': 844, 'deviceScaleFactor': 3, 'mobile': True},
    'galaxy_s23': {'width': 360, 'height': 780, 'deviceScaleFactor': 3, 'mobile': True},
    'ipad_mini': {'width': 768, 'height': 1024, 'deviceScaleFactor': 2, 'mobile': True},
}

def mobile_screenshot(url, device='iphone14'):
    config = DEVICES.get(device, DEVICES['iphone14'])

    response = requests.post(
        'https://api.toolcenter.dev/v1/screenshot',
        json={'url': url, 'format': 'png', **config},
        headers={'Authorization': 'Bearer YOUR_API_KEY'}
    )

    return response.content

Capturing All Breakpoints at Once

Test your site across all device sizes in one shot:

const fs = require('fs');

async function captureAllBreakpoints(url) {
  const breakpoints = [
    { name: 'mobile-small', width: 320, height: 568, mobile: true, deviceScaleFactor: 2 },
    { name: 'mobile', width: 375, height: 667, mobile: true, deviceScaleFactor: 2 },
    { name: 'mobile-large', width: 430, height: 932, mobile: true, deviceScaleFactor: 3 },
    { name: 'tablet', width: 768, height: 1024, mobile: true, deviceScaleFactor: 2 },
    { name: 'laptop', width: 1280, height: 800, mobile: false, deviceScaleFactor: 1 },
    { name: 'desktop', width: 1920, height: 1080, mobile: false, deviceScaleFactor: 1 },
  ];

  const results = await Promise.all(
    breakpoints.map(async (bp) => {
      const response = await axios.post(
        'https://api.toolcenter.dev/v1/screenshot',
        {
          url: url,
          width: bp.width,
          height: bp.height,
          mobile: bp.mobile,
          deviceScaleFactor: bp.deviceScaleFactor,
          format: 'png',
        },
        {
          headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
          responseType: 'arraybuffer',
        }
      );
      return { name: bp.name, data: response.data };
    })
  );

  // Save all screenshots
  for (const result of results) {
    fs.writeFileSync(`screenshots/${result.name}.png`, result.data);
  }

  return results;
}

User Agent Strings

Mobile sites sometimes serve different content based on the User-Agent. Set it to match the device:

const response = await axios.post(
  'https://api.toolcenter.dev/v1/screenshot',
  {
    url: 'https://example.com',
    width: 390,
    height: 844,
    mobile: true,
    deviceScaleFactor: 3,
    userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
    format: 'png',
  },
  {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    responseType: 'arraybuffer',
  }
);

Landscape Mode

Capture landscape orientations by swapping width and height:

async function landscapeScreenshot(url) {
  const response = await axios.post(
    'https://api.toolcenter.dev/v1/screenshot',
    {
      url: url,
      width: 844,   // iPhone 14 height becomes landscape width
      height: 390,   // iPhone 14 width becomes landscape height
      mobile: true,
      deviceScaleFactor: 3,
      format: 'png',
    },
    {
      headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
      responseType: 'arraybuffer',
    }
  );
  return response.data;
}

Automating Responsive Testing in CI/CD

Integrate mobile screenshots into your deployment pipeline:

# .github/workflows/responsive-test.yml
name: Responsive Design Test
on:
  pull_request:
    branches: [main]

jobs:
  screenshots:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install
      - run: node scripts/capture-responsive.js
        env:
          DEVTOOLBOX_API_KEY: ${{ secrets.DEVTOOLBOX_API_KEY }}
          TARGET_URL: ${{ github.event.deployment.environment_url }}
      - uses: actions/upload-artifact@v4
        with:
          name: responsive-screenshots
          path: screenshots/

Building a Responsive Preview Dashboard

Create a simple dashboard that shows all device previews:

const express = require('express');
const app = express();

app.get('/preview', async (req, res) => {
  const { url } = req.query;
  if (!url) return res.status(400).send('URL required');

  const devices = [
    { name: 'iPhone SE', width: 375, height: 667, mobile: true, deviceScaleFactor: 2 },
    { name: 'iPhone 14', width: 390, height: 844, mobile: true, deviceScaleFactor: 3 },
    { name: 'iPad', width: 768, height: 1024, mobile: true, deviceScaleFactor: 2 },
    { name: 'Desktop', width: 1440, height: 900, mobile: false, deviceScaleFactor: 1 },
  ];

  const screenshots = await Promise.all(
    devices.map(async (device) => {
      const response = await axios.post(
        'https://api.toolcenter.dev/v1/screenshot',
        { url, ...device, format: 'png' },
        { headers: { 'Authorization': 'Bearer YOUR_API_KEY' }, responseType: 'arraybuffer' }
      );
      const base64 = Buffer.from(response.data).toString('base64');
      return { ...device, image: `data:image/png;base64,${base64}` };
    })
  );

  const html = `
    <html><body style="font-family:system-ui;padding:20px;">
    <h1>Responsive Preview: ${url}</h1>
    <div style="display:flex;gap:20px;flex-wrap:wrap;">
      ${screenshots.map(s => `
        <div style="text-align:center;">
          <h3>${s.name} (${s.width}×${s.height})</h3>
          <img src="${s.image}" style="max-width:300px;border:1px solid #ddd;border-radius:8px;" />
        </div>
      `).join('')}
    </div></body></html>
  `;

  res.send(html);
});

app.listen(3000);

Monitoring Responsive Breakages

Set up automated checks that catch responsive issues:

import requests
from PIL import Image
from io import BytesIO

def check_responsive(url):
    issues = []

    # Capture mobile screenshot
    response = requests.post(
        'https://api.toolcenter.dev/v1/screenshot',
        json={'url': url, 'width': 375, 'height': 667, 'mobile': True, 'fullPage': True, 'format': 'png'},
        headers={'Authorization': 'Bearer YOUR_API_KEY'}
    )

    img = Image.open(BytesIO(response.content))

    # Check if page is wider than viewport (horizontal scroll)
    if img.width > 375 * 2:  # Account for device scale factor
        issues.append('Horizontal overflow detected on mobile')

    # Check if page is extremely tall (possible layout break)
    if img.height > 667 * 2 * 10:
        issues.append('Page is unusually tall on mobile — possible layout issue')

    return issues

Conclusion

Mobile screenshot testing with the ToolCenter eliminates the need for device farms and manual testing. Capture every viewport size programmatically, integrate it into your CI/CD pipeline, and catch responsive design issues before your users do. The parallel request support means you can test 6+ breakpoints in the time it takes to capture one screenshot.