Mobile Viewport Testing With a Screenshot API: What Actually Works
Use a mobile screenshot API for reliable viewport testing across iPhone, Android, and tablet sizes. Real configs, device pixel ratios, and CI examples.
Responsive design breaks in the places you don't look. A button overlaps a sticky footer on iPhone SE. A modal scrolls off-screen on a Pixel 7. Your hero image becomes 4MB on a slow Android. The only reliable way to catch these regressions without buying a device lab is automated viewport testing — and a mobile screenshot API is the cheapest, most scriptable way to do it.
This post walks through what actually matters when configuring a mobile screenshot API for viewport testing: which devices to target, how device pixel ratio (DPR) trips people up, and how to wire it into CI without flaky results.
Why a screenshot API beats local browser automation
You can technically do mobile viewport testing with Playwright or Puppeteer locally. People do. But here's what breaks:
- Font rendering differs between your Mac, your Linux CI runner, and an actual mobile device. Subpixel hinting, emoji fonts, and system fallbacks all vary.
- Headless Chrome on CI doesn't ship with the same font set as production browsers, so screenshots diff against themselves between branches.
- Cold-start times for spinning up browsers in CI add 10-30 seconds per job.
- Maintenance — keeping browser binaries, fonts, and emulation profiles up to date is a recurring tax.
A hosted screenshot API offloads all of that. You send a URL with viewport parameters, you get a PNG back. That's it.
The device matrix that actually matters
You don't need to test 40 devices. You need to cover the breakpoints where layouts actually change. Here's a practical baseline:
Small phones (320–375px)
- iPhone SE (375x667, DPR 2)
- Galaxy S8 (360x740, DPR 3)
Standard phones (390–414px)
- iPhone 14 (390x844, DPR 3)
- Pixel 7 (412x915, DPR 2.625)
Large phones / phablets (428–430px)
- iPhone 14 Pro Max (430x932, DPR 3)
Tablets (768–1024px)
- iPad Mini (768x1024, DPR 2)
- iPad Pro 11" (834x1194, DPR 2)
iPhone SE and iPhone 14 Pro Max alone will catch 80% of mobile layout bugs. Add an iPad and you've covered the tablet edge cases too.
Device pixel ratio: the silent killer
Most screenshot bugs come from confusing CSS pixels with device pixels. If you request a 390-wide screenshot at DPR 3, you get a 1170px-wide image. Your visual diff tool will scream regression when nothing actually changed — the previous run was at DPR 2.
Lock DPR explicitly in every request. Don't rely on defaults. With PxShot you'd pass something like:
GET https://api.pxshot.dev/v1/screenshot
?url=https://yoursite.com/pricing
&viewport_width=390
&viewport_height=844
&device_pixel_ratio=3
&format=png
&full_page=true
Keep DPR consistent per device profile. iPhone is 3, iPad is 2, most Android mid-range is 2.625 or 3.
Handling full-page vs. fold screenshots
Two different jobs, two different configs:
- Above-the-fold capture — for OG images, hero-section regression checks, and Lighthouse-style first-paint validation. Use the exact viewport height (e.g. 844px for iPhone 14) and disable full-page.
- Full-page capture — for layout audits, scroll-jacking bugs, and reviewing the entire mobile experience. Enable full-page and expect tall outputs (often 5000-15000px).
Full-page captures on mobile viewports also expose lazy-loaded images that haven't fired. Add a scroll-through wait or a fixed delay (3-5s) before capture so IntersectionObserver-triggered images actually load.
Wiring it into CI
Here's a minimal GitHub Actions step that captures screenshots across three viewports on every PR and uploads them as artifacts:
- name: Capture mobile screenshots
run: |
for device in "iphone-se:375:667:2" "iphone-14:390:844:3" "ipad:768:1024:2"; do
IFS=':' read name w h dpr <<< "$device"
curl -o "screenshots/$name.png" "https://api.pxshot.dev/v1/screenshot?url=${PREVIEW_URL}&viewport_width=${w}&viewport_height=${h}&device_pixel_ratio=${dpr}&full_page=true&api_key=${PXSHOT_KEY}"
done
- uses: actions/upload-artifact@v4
with:
name: mobile-screenshots
path: screenshots/
Pair this with a visual diff tool like Pixelmatch or Reg-suit to compare against baselines stored in S3. The diffs surface in PR comments and reviewers can eyeball them in seconds.
Common gotchas worth knowing
- User agent mismatch. Setting a mobile viewport but leaving the desktop user agent means your server might return the desktop HTML. Set the UA string to match the device you're emulating.
- Sticky elements. Position-fixed headers and cookie banners get captured repeatedly in stitched full-page screenshots. Either dismiss them via a pre-capture script or set
full_page_scroll=trueoptions that hide stickies after the first viewport. - Web fonts. Custom fonts via Google Fonts or self-hosted woff2 occasionally miss the load window. Add a 1-2s render delay or wait for
document.fonts.ready. - Animations. CSS animations that loop will look different every capture. Inject CSS that disables animations before screenshotting.
- Authentication. For staging environments, pass basic auth or a session cookie via the API's auth parameters rather than baking credentials into the URL.
What to actually assert on
Pixel-perfect diffs are noisy. Instead, build assertions around:
- Layout shifts — has any element moved more than 10px from baseline?
- Overflow — does total page width exceed viewport width on mobile? That's an instant horizontal-scroll bug.
- Critical components — crop to specific selectors (header, primary CTA, pricing cards) and diff just those regions. PxShot supports element-targeted captures via a CSS selector parameter, which keeps diffs stable when unrelated content changes.
- File size — a sudden 3x jump in screenshot file size often signals an unoptimised image landed on the page.
Test what your users actually see
The point of mobile viewport testing isn't to have a folder full of PNGs. It's to catch the moment when a copy change pushes your CTA below the fold on iPhone SE, or when a new component breaks scrolling on Android. Run captures on every deploy, store baselines, and diff aggressively.
If you want to skip the browser-binary maintenance and just hit an endpoint, PxShot has a free tier that covers small projects and side experiments — enough requests per month to wire up a real mobile viewport testing pipeline without a credit card.