How to Capture Mobile Website Screenshots with Browserless and a Device Profile
Capture mobile website screenshots with Browserless: configure Android device emulation, choose REST or BQL, and handle full-page captures and common pitfalls.
To capture a mobile website screenshot with Browserless device emulation, connect to a supported Browserless stealth or BrowserQL (BQL) endpoint with emulationOs=android. You can optionally add a supported emulatedDevice slug. For a direct URL-to-image request, Browserless also offers POST /screenshot; its documented screenshot options cover viewport and device scale factor, but the Android profile setting is documented for supported stealth or BQL connections. Use BQL when you need to set up that profile and explicitly navigate, wait, or capture within a browser session. Browserless documents Android emulation, not iPhone, iOS, or Safari emulation.
1. Choose the capture workflow
| Workflow | Use it for | Mobile setup |
|---|---|---|
| REST Screenshot API | A direct URL-to-image request with screenshot options. | Use documented endpoint options. Do not assume the Android profile parameter works on this endpoint. |
| BQL session | A browser session that needs explicit navigation, viewport or screenshot mutations. | Pass emulationOs=android on an eligible connection URL, then navigate and capture using BQL. |
Get a Browserless API token from your account dashboard. Keep it in an environment variable or secret store rather than committing it to source code; that is standard credential-handling advice. Browserless requires a token for its Screenshot API. See the Screenshot API documentation.
2. Capture a screenshot with the REST API
The documented REST workflow sends a POST request to /screenshot with a URL and optional screenshot options. The token goes in the endpoint query string, and the response contains image bytes. This example saves the response as a PNG; replace the illustrative endpoint host with the Browserless endpoint for your account or deployment.
export BROWSERLESS_TOKEN='YOUR_TOKEN'
export BROWSERLESS_SCREENSHOT_ENDPOINT='https://YOUR_BROWSERLESS_ENDPOINT/screenshot'
curl -X POST "$BROWSERLESS_SCREENSHOT_ENDPOINT?token=$BROWSERLESS_TOKEN" \
-H 'Content-Type: application/json' \
--data '{"url":"https://example.com","options":{"fullPage":true,"scrollPage":true,"type":"png"}}' \
--output screenshot.png
Use the endpoint and option names accepted by your Browserless deployment. Browserless documents PNG, JPEG, and WebP output, full-page capture, viewport and device scale factor options, clipping, and selector capture. For lazy-loaded content in a full-page screenshot, set scrollPage: true so the page is scrolled before capture.
3. Use Android device emulation in a BQL session
For the documented mobile device profile, pass emulationOs=android as a connection query parameter on a supported stealth or BQL endpoint. You may add a supported, case-sensitive emulatedDevice slug. The following illustrates the setup and the BQL operations; use the connection URL and client syntax required by your Browserless account.
export BROWSERLESS_BQL_URL='wss://YOUR_SUPPORTED_BROWSERLESS_ENDPOINT?token=YOUR_TOKEN&emulationOs=android&emulatedDevice=YOUR_DEVICE_SLUG'
# Connect a BQL client to BROWSERLESS_BQL_URL, then execute:
mutation {
goto(url: "https://example.com") {
status
}
}
After navigation, wait for the content your capture needs, then use the BQL screenshot mutation. The mutation supports full-page, selector, clip, type, quality, timeout, and image-wait controls. For example, the shape of a capture mutation is:
mutation {
screenshot(options: {
fullPage: true,
type: png,
waitForImages: true,
timeout: 30000
})
}
Use the exact input syntax and return handling supported by your BQL client and schema. BQL returns the capture through the session workflow; save or decode those returned bytes according to the client you use. See the OS emulation guide and the screenshot mutation reference.
4. Understand what the device profile changes
Browserless’s Android profile supplies more than screen dimensions. Its documented Android signals include a mobile Chrome identity, model information through User-Agent Client Hints, phone screen size and pixel ratio, touch behavior, and portrait orientation. That makes it a broader emulated device identity than setting a viewport alone. It remains software emulation, not a capture from a physical handset.
An optional emulatedDevice selects a supported Android model. It requires emulationOs=android; Browserless documents an HTTP 400 response for using the device parameter without Android emulation on a stealth request. Slugs are case-sensitive. An unrecognized slug falls back to an automatically selected device rather than necessarily failing. The documented profiles represent modern flagship phones in portrait orientation; do not treat them as arbitrary legacy devices or a way to rotate a profile to landscape.
5. Device profile versus manual viewport
| Setting | Controls | Good fit |
|---|---|---|
| Android device profile | A broader mobile identity, including browser/client hints and device signals, as well as screen characteristics. | Captures that need a documented Android emulation profile. |
| Manual BQL viewport | Width, height, device scale factor, mobile mode, touch support, and landscape settings. | Specific dimensions or viewport behavior without a device profile. |
Browserless shows 375 × 667 with mobile: true as an example viewport, not a universal device recommendation. With a profile active, orientation comes from the device’s screen shape; the viewport mutation’s landscape setting takes effect only when no device-emulation profile is active. Consult the viewport mutation reference.
mutation {
viewport(width: 375, height: 667, deviceScaleFactor: 2, mobile: true, touch: true) {
width
height
}
}
Use manual viewport settings when dimensions are the requirement. Do not assume that a manually set viewport or user agent reproduces all signals supplied by the Android profile.
6. Configure the screenshot and page readiness
- Format: Choose PNG, JPEG, or WebP where supported by the selected workflow. Confirm the response content type and use a matching filename extension.
- Full page: Enable full-page capture when you need the full document. In the REST API, use
scrollPage: truewhen lazy-loaded material must be brought into view. - Selector or clip: Capture a specific element with selector capture, or restrict output to a clip when you only need part of the page.
- Scale and dimensions: Set viewport and device scale factor deliberately. CSS viewport dimensions and output pixel dimensions are related but not identical when scale factor changes.
- Wait for content: In BQL, wait for navigation and relevant page content before capture. The screenshot mutation exposes timeout and
waitForImages; image completion alone may not mean a client-rendered widget or delayed content is ready. - Output handling: The REST response is binary image data. Do not treat it as JSON; check HTTP status and content type before saving it.
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 400 when selecting a device | emulatedDevice was sent without emulationOs=android, or the connection endpoint does not support that emulation option. |
Add the Android parameter to a supported stealth or BQL connection URL and verify the endpoint. |
| Unexpected device profile | The device slug may be misspelled, incorrectly cased, or unrecognized; unknown slugs can fall back to automatic selection. | Use a supported, case-sensitive slug and inspect the resulting capture. |
| Screenshot looks like desktop | A manual viewport or a screenshot request alone does not establish the documented Android profile. | Use an eligible BQL or stealth connection with emulationOs=android when you need that profile. |
| Lazy content is missing in a full-page image | The content did not load because its lazy-loading trigger was never reached. | For the REST screenshot workflow, enable scrollPage: true; otherwise explicitly scroll and wait in the session workflow. |
| Screenshot is clipped or too small | Viewport dimensions, scale factor, selector, or clip settings do not match the intended output. | Check the active device profile and viewport settings, then adjust the capture bounds. |
| Landscape setting has no effect | An active device profile controls orientation from its screen shape. | Use portrait for the documented profile, or configure a manual viewport without an active profile if that meets the use case. |
| Image file contains an error or looks corrupted | An HTTP error response may have been saved as if it were image bytes, or the extension may not match the requested format. | Check status and content type before writing the response; inspect the error body separately. |
| 401 or authorization failure | The token is absent, invalid, or attached incorrectly. | Check the token and the documented endpoint authentication format; avoid placing credentials in shared logs or repositories. |
8. Performance, reliability, and cost considerations
Capture time depends on target-page loading and the waits or scrolling needed for its content; the cited Browserless documentation provides no general performance benchmark to rely on. Keep waits tied to the content you need, use image waiting only when appropriate, and avoid full-page capture if a selector or clip meets the requirement. Full-page lazy loading can add page work because the page must be scrolled to reveal deferred content.
For repeatable QA, record the URL, chosen profile slug, viewport or scale settings, format, and readiness condition alongside each capture. Validate representative pages with dynamic content, consent overlays, and long pages. Treat a cloud-emulated profile as an automated layout check; use the actual target browser and device for any behavior that depends on physical hardware or iOS/Safari. Browserless’s documentation contains no named screenshot success rate or performance statistic, so none is stated here. Pricing depends on the Browserless account and deployment; consult its current account details rather than assuming a rate from this guide.
9. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. For a straightforward URL-to-image capture, call its API directly. The following example saves the response body; use the response handling appropriate for your runtime.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));
See the ScreenshotNeo API documentation for request options. ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients use screenshot tools. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is available on every plan. The API supports PNG, JPEG, WebP, and PDF, along with full-page and selector capture, device presets and custom viewports, custom CSS and JavaScript, waits, caching, async jobs, bulk capture, and other options.
Sign up free for 1,000 screenshots a month with no card.
10. FAQ
Can I use this Browserless profile to test iPhone Safari?
No. The documented device-profile emulation supports Android. Browserless says iPhone, iOS, and Safari are unsupported by this emulation.
Can the REST Screenshot API capture a full page?
Yes. The Screenshot API documents full-page capture. Set scrollPage: true when lazy-loaded content needs to be triggered before the capture.
Should I use a device profile or a custom viewport?
Use a profile when you need the broader documented Android identity. Use a manual viewport when you need specific dimensions and viewport behavior. They are not equivalent.
Does an unknown device slug always return an error?
No. Browserless documents automatic device selection as a fallback for an unrecognized slug, so verify the resulting screenshot rather than relying on the slug being accepted as intended.


