Mobile screenshots
To capture what a page looks like on a phone or tablet, you have two tools: a device preset that sets everything in one word, or a custom viewport where you set each property. This guide explains which to use and why a narrow viewport alone is often not enough. It is part of the capture guides.
The minimal request
The requests below need an API key in RS_API_KEY (get one free).
GET, with a device preset:
curl -G "https://api.renderscreenshot.com/v1/screenshot" \ -H "Authorization: Bearer $RS_API_KEY" \ --data-urlencode "url=https://example.com" \ -d device=iphone_14 \ -o iphone.png
POST, with the same preset:
curl -X POST https://api.renderscreenshot.com/v1/screenshot \ -H "Authorization: Bearer $RS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "viewport": { "device": "iphone_14" } }' \ -o iphone.png
The response is a 1170 x 2532 PNG: a 390 x 844 viewport at a device scale of 3.
Three ways to get a mobile capture
| Approach | You set | Good for |
|---|---|---|
device preset |
One id, for example iphone_14, pixel_7 or ipad_air |
Realistic captures of a known device |
preset: mobile or mobile_landscape |
One preset that also sets format and cache defaults | Quick portrait or landscape phone shots |
Custom viewport |
width, height, scale, mobile, touch, landscape |
A device that is not in the list, or exact control for tests |
A device preset overrides width, height, scale and mobile. Set landscape: true next to a device to swap width and height.
Why width alone is not enough
Many teams start with width: 390 and get a desktop page squeezed into a narrow window. That happens because three separate things make a browser behave like a phone:
- The layout viewport. A real phone honours the page's
<meta name="viewport" content="width=device-width">tag. Chrome applies that tag only in mobile emulation, which isviewport.mobile: true. Without it, a page that has no tag still lays out at a desktop width. - Input capabilities. Media queries such as
(hover: none)and(pointer: coarse)describe a touch screen.viewport.touch: trueturns on touch events, which some sites check before they show the mobile menu or swipe controls. - The user agent. Some sites choose the mobile template on the server by reading the
User-Agentheader. A narrow window with a desktop user agent gets the desktop HTML. Device presets send that device's user agent; with a custom viewport, setbrowser.user_agentyourself. The custom user agent guide shows the effect.
A device preset handles all three, so start there. Switch to a custom viewport only when you need a size that is not in the list.
Device presets
Get the current list from the API rather than from a copy in your code:
curl https://api.renderscreenshot.com/v1/devices \ -H "Authorization: Bearer $RS_API_KEY"
Each entry has an id, a viewport (width and height in CSS pixels), a scale, and the mobile and touch flags. A selection:
| Device id | Viewport (CSS px) | Scale | Output image (px) |
|---|---|---|---|
iphone_se |
375 x 667 | 2 | 750 x 1334 |
iphone_14 |
390 x 844 | 3 | 1170 x 2532 |
pixel_7_pro |
412 x 892 | 3.5 | 1442 x 3122 |
ipad_air |
820 x 1180 | 2 | 1640 x 2360 |
ipad_pro_12 |
1024 x 1366 | 2 | 2048 x 2732 |
The output size is always viewport times scale. A large scale makes large files: see retina screenshots for the measured cost, and use viewport.scale: 1 together with a device-sized custom viewport if you only need the layout.
An unknown device id fails with a validation_error (HTTP 400) before any rendering, so a typo never uses a credit.
Custom viewport
For a device that is not in the list, set the properties yourself:
{ "url": "https://example.com", "viewport": { "width": 360, "height": 780, "scale": 3, "mobile": true, "touch": true }, "browser": { "user_agent": "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36" } }
| Parameter | Default | Limits | Effect |
|---|---|---|---|
viewport.width |
1280 |
1 to 7,680 | Layout width in CSS pixels |
viewport.height |
800 |
1 to 4,320 | Visible height; also the image height in viewport mode |
viewport.scale |
1 |
1 to 3 | Device pixel ratio; multiplies output pixels |
viewport.mobile |
false |
Applies the meta viewport tag, as a phone does | |
viewport.touch |
false |
Enables touch events | |
viewport.landscape |
false |
Swaps width and height |
Custom scale accepts 1 to 3. Device presets can use their real ratio, for example 3.5 for pixel_7_pro.
Full-page mobile captures
Mobile pages are long. Combine a device with full-page capture to get the whole scroll height at the device width:
{ "url": "https://example.com/blog/post", "viewport": { "device": "iphone_14" }, "capture": { "mode": "full_page", "scroll": { "simulate": true } } }
At scale 3, a 6,000 px tall mobile page becomes an 18,000 px tall image. If the image is for a web page or for a vision model, set viewport.scale: 1 or resize the output. The full-page guide covers scroll.max_height.
SDK examples
Device preset first, then a custom viewport.
Node.js
import { writeFile } from 'node:fs/promises'; import { Client, TakeOptions } from 'renderscreenshot'; const client = new Client(process.env.RS_API_KEY); const phone = await client.take(TakeOptions.url('https://example.com').device('iphone_14')); await writeFile('iphone.png', phone); const custom = await client.take( TakeOptions.url('https://example.com').width(360).height(780).scale(3).mobile() ); await writeFile('custom.png', custom);
Python
import os from renderscreenshot import Client, TakeOptions client = Client(os.environ['RS_API_KEY']) phone = client.take(TakeOptions.url('https://example.com').device('iphone_14')) custom = client.take( TakeOptions.url('https://example.com').width(360).height(780).scale(3).mobile() ) with open('iphone.png', 'wb') as f: f.write(phone)
Ruby
require 'renderscreenshot' client = RenderScreenshot.client(ENV.fetch('RS_API_KEY')) phone = client.take(RenderScreenshot::TakeOptions.url('https://example.com').device('iphone_14')) custom = client.take( RenderScreenshot::TakeOptions.url('https://example.com').width(360).height(780).scale(3).mobile ) File.binwrite('iphone.png', phone)
PHP
use RenderScreenshot\Client; use RenderScreenshot\TakeOptions; $client = new Client(getenv('RS_API_KEY')); $phone = $client->take(TakeOptions::url('https://example.com')->device('iphone_14')); $custom = $client->take( TakeOptions::url('https://example.com')->width(360)->height(780)->scale(3)->mobile() ); file_put_contents('iphone.png', $phone);
Java
Client client = new Client(System.getenv("RS_API_KEY")); byte[] phone = client.take(TakeOptions.url("https://example.com").device("iphone_14")); byte[] custom = client.take( TakeOptions.url("https://example.com").width(360).height(780).scale(3.0).mobile() ); Files.write(Path.of("iphone.png"), phone);
Go
phone, err := client.Take(ctx, rs.URL("https://example.com").Device("iphone_14")) if err != nil { log.Fatal(err) } custom, err := client.Take(ctx, rs.URL("https://example.com").Width(360).Height(780).Scale(3).Mobile(), ) if err != nil { log.Fatal(err) } os.WriteFile("iphone.png", phone, 0o644) os.WriteFile("custom.png", custom, 0o644)
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Desktop layout in a narrow image | mobile not set, so the meta viewport tag is ignored |
Use a device preset or set viewport.mobile: true |
| Mobile layout, but tiny text | The page has no meta viewport tag | Expected for such pages; this is what a phone shows too |
Desktop HTML even with mobile: true |
The server picks the template from the user agent | Use a device preset, or set browser.user_agent to a mobile string |
| Hamburger menu or swipe UI missing | Site checks for touch support | Set viewport.touch: true |
| App install banner or cookie sheet covers the page | Mobile-only overlays | block.cookie_banners: true, or page.hide with the banner selector |
| Image is huge | Scale 3 times full page height | Use viewport.scale: 1 or output.resize |
validation_error naming the device |
Device id not in the list | Check GET /v1/devices |
| Landscape needed | Portrait is the default | viewport.landscape: true or preset: mobile_landscape |
Related
- Devices reference and
GET /v1/devices. - Viewport parameters.
- Retina screenshots for scale and file size.
- Presets reference for
mobileandmobile_landscape.