ScreenshotNeo

BlogHow-to

How to Capture a Mobile Website Screenshot with Browserless

Capture a mobile website screenshot with Browserless using its REST API, configure viewport and device emulation, and handle full-page captures and common issues.

By the ScreenshotNeo team4 October 20268 min read

To capture a mobile website screenshot with Browserless, send an authenticated POST request to its /screenshot endpoint with the target URL and screenshot options. Set the viewport to the phone-sized width and height you want to inspect. For richer mobile behavior, Browserless BrowserQL exposes mobile, touch, device scale, and orientation settings; these belong to its browser-session workflow and are not interchangeable with the REST request body.

A mobile-width screenshot shows how a responsive layout renders at that viewport. It does not automatically reproduce every phone property or guarantee an iPhone, iOS, or Safari environment. Browserless documents Android emulation for certain BrowserQL stealth sessions; its emulation guide says iPhone, iOS, and Safari are not supported by that feature.

1. Get a Browserless token and choose the capture

Obtain an API token from your Browserless account dashboard. The documented REST screenshot flow uses that token in the endpoint query string. Before sending the request, decide what the image should show:

Capture Use it for Browserless option
Visible viewport The initial phone screen or a specific scroll position Viewport width and height
Full page The complete length of a long page fullPage: true
Element A component or section selected by CSS Top-level selector
Fixed region A known rectangle within the page clip coordinates and dimensions

Choose dimensions in CSS pixels based on the layout you need to inspect. There is no single canonical phone viewport for every site. A viewport capture is usually the right starting point when the goal is to check responsive behavior above the fold.

2. Capture a mobile-sized viewport with the REST API

The REST endpoint accepts a POST request with a URL and an options object. The response is image data, so save it as a binary file rather than treating it as JSON. The example below uses placeholders for the token and target site. Consult the Browserless Screenshot API documentation for the currently supported option names and values for your deployed version.

curl -X POST "https://production-sfo.browserless.io/screenshot?token=YOUR_BROWSERLESS_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "url": "https://example.com",
    "options": {
      "viewport": { "width": 390, "height": 844 },
      "type": "png"
    }
  }' \
  --output mobile.png

Replace YOUR_BROWSERLESS_TOKEN and https://example.com. Change the viewport dimensions to the CSS-pixel dimensions you want. If your endpoint version expects viewport fields in a different supported shape, follow its current REST schema; do not copy BrowserQL mutation syntax into this JSON body.

Python

This example uses requests. Install it with python -m pip install requests if needed.

import requests

endpoint = "https://production-sfo.browserless.io/screenshot"
params = {"token": "YOUR_BROWSERLESS_TOKEN"}
payload = {
    "url": "https://example.com",
    "options": {
        "viewport": {"width": 390, "height": 844},
        "type": "png",
    },
}

response = requests.post(endpoint, params=params, json=payload, timeout=90)
response.raise_for_status()

with open("mobile.png", "wb") as image_file:
    image_file.write(response.content)

Node.js

This example uses the built-in fetch available in current Node.js versions. It checks the HTTP response before writing the returned bytes.

import { writeFile } from "node:fs/promises";

const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", "YOUR_BROWSERLESS_TOKEN");

const response = await fetch(endpoint, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    url: "https://example.com",
    options: {
      viewport: { width: 390, height: 844 },
      type: "png",
    },
  }),
  signal: AbortSignal.timeout(90_000),
});

if (!response.ok) {
  throw new Error(`Browserless returned HTTP ${response.status}: ${await response.text()}`);
}

await writeFile("mobile.png", Buffer.from(await response.arrayBuffer()));

3. Use BrowserQL when you need mobile session settings

BrowserQL configures a browser session with a viewport mutation. Its documented arguments include width, height, device scale factor, and mobile; touch and landscape are optional. This provides more explicit device-like behavior than setting a mobile-sized viewport alone. Use the BrowserQL schema for its exact request and screenshot syntax rather than assuming REST options have the same shape.

mutation CaptureMobile {
  goto(url: "https://example.com") {
    status
  }
  setViewport(
    width: 390,
    height: 844,
    deviceScaleFactor: 3,
    mobile: true,
    hasTouch: true,
    landscape: false
  ) {
    width
    height
  }
  screenshot(type: png) {
    # Follow the current BrowserQL schema for returned screenshot data.
  }
}

The mutation outline illustrates the viewport arguments documented by Browserless. Check the current BrowserQL viewport documentation and screenshot operation documentation for the valid schema, operation ordering, and how your client receives image output. The screenshot mutation documents a default 30-second timeout; configure an appropriate timeout when your workflow needs more time.

Android emulation limits

For certain BrowserQL stealth sessions, Browserless documents emulationOs=android. Its guide describes mobile Chrome on Android with phone dimensions, a high pixel ratio, touch input, and portrait orientation. That feature does not establish iPhone, iOS, or Safari fidelity. If you need to verify a specific real-device browser, use a workflow that explicitly supports that device and browser.

4. Choose full page, element, clip, and output options

Use the framing option that matches the question you are answering. REST screenshot documentation lists viewport sizing, device scale factor, full-page capture, element selection, clipping, output formats, and quality options. Confirm the exact accepted fields against the endpoint version you call.

  • Viewport: captures the visible browser area at the configured dimensions.
  • Full page: set fullPage: true when you need the full document. This may take longer and produce a much taller, larger image.
  • Element: set the documented top-level selector to a CSS selector. Browserless captures the selected element’s bounding box. The selector must match an element that exists when capture occurs.
  • Clip: use a rectangle with coordinates and dimensions when you know the exact region to capture.
  • Format: Browserless documents PNG, JPEG, and WebP response formats. PNG is useful when lossless detail matters; compressed formats can reduce output size.
  • Quality: use the documented quality option for lossy formats where supported. Quality does not apply to PNG in the BrowserQL screenshot operation.
  • Device scale factor: controls how many output pixels represent a CSS pixel. A higher factor can make small details sharper while increasing image dimensions and bytes.

Do not combine full-page, selector, and clip settings casually. They describe different capture bounds; check the REST schema for supported combinations and use one framing method that matches the desired result.

5. Wait for dynamic content and lazy-loaded images

A page can return its initial HTML before the content you care about appears. Wait for the relevant element or documented load condition before capturing. Browserless warns that waiting for page content helps avoid blank or incomplete screenshots. If images load only after scrolling into view, the REST API documents scrollPage: true, which can be paired with fullPage: true.

{
  "url": "https://example.com/catalog",
  "options": {
    "viewport": { "width": 390, "height": 844 },
    "fullPage": true,
    "scrollPage": true,
    "type": "webp"
  }
}

The snippet shows the documented options to consider; use the current REST API documentation for the supported wait fields and their exact structure. Prefer a meaningful condition, such as the selector for the content you need, over an unnecessarily long fixed delay. For pages where a fixed delay is unavoidable, keep it bounded so slow pages do not consume a browser session indefinitely.

6. Troubleshooting

Symptom Likely cause What to try
401 or 403 response The token is missing, invalid, or not accepted for the endpoint. Check the token in the account dashboard, confirm the endpoint host and query parameter, and avoid publishing a real token in code or logs.
JSON parsing error while saving The screenshot response was treated as JSON instead of binary image bytes, or the server returned an error payload. Save the successful response body as bytes. On errors, inspect the HTTP status and error response before writing the file.
Image has desktop layout The requested viewport was not applied or the site uses another breakpoint. Verify the REST viewport option against the REST schema. For mobile behavior controls, use BrowserQL’s viewport settings and inspect the resulting dimensions.
Screenshot is blank or content is missing The page has not finished rendering, a selector is absent, or resources are loaded asynchronously. Wait for the needed content with a documented wait condition. Confirm the target URL is accessible and that your selector matches.
Lazy images are absent in a full-page image The images load only after scrolling into view. Try the documented scrollPage: true with fullPage: true.
Element capture fails or is empty The CSS selector does not match, matches too early, or identifies a hidden element. Check the selector in the rendered page and wait until the element is visible before capturing.
CAPTCHA, access denied, or bot-check page appears The destination may block automated browsing. Respect the site’s access controls and terms. Do not assume an unblock workflow will succeed; Browserless documents an /unblock route for anti-bot cases, but it cannot guarantee access.
Timeout on a long page Navigation, network requests, lazy loading, or full-page rendering takes longer than the configured limit. Wait for the specific content needed, avoid capturing more page than necessary, and increase the timeout only within the limits of your service configuration.

7. Performance, reliability, and cost considerations

  • Keep the capture scope small: a viewport or element capture generally has less work than scrolling and rendering a long full-page document.
  • Use the right pixel density: larger dimensions and higher device scale factors increase output pixel count and file size. Choose based on inspection or display needs.
  • Make waits specific: waiting for a needed selector can avoid both premature captures and excessive fixed delays.
  • Handle failures explicitly: check HTTP status before saving output, set a client timeout suitable for the page, and record errors without exposing tokens.
  • Expect destination variability: dynamic content, network conditions, bot checks, and access controls can change what a remote browser sees. A successful HTTP request does not guarantee the intended content rendered.
  • Check current service pricing: the research sources establish the endpoint and token workflow but do not provide current Browserless pricing or usage limits. Review the provider’s current account terms before planning volume or cost.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF, and its parameters are designed to make switching from other screenshot APIs straightforward. Its clean-shot flow accepts cookie consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the response identifying the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents.

See the ScreenshotNeo API documentation. This call saves a mobile-sized WebP screenshot; choose the viewport dimensions that fit your target layout.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com \
  -d width=390 \
  -d height=844 \
  -o mobile.webp

ScreenshotNeo includes 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 screenshots. Sign up for free and capture your first 1,000 screenshots a month with no card.

9. Frequently asked questions

Does a mobile viewport make the screenshot equivalent to a phone?

It applies a viewport size. BrowserQL can also configure mobile, touch, scale factor, and orientation; those settings still do not mean every real phone and browser is reproduced.

Can Browserless capture an iPhone Safari screenshot with Android emulation?

No. Browserless’s documented OS emulation feature covers Android and explicitly says iPhone, iOS, and Safari are unsupported by that feature.

Should I use PNG, JPEG, or WebP?

Choose PNG when lossless output matters; choose JPEG or WebP when a smaller lossy image suits the downstream use. Confirm format and quality support on the API surface you use.

Why does a full-page screenshot take longer than a viewport capture?

It may need to render and capture substantially more page content, and lazy-loaded resources may require scrolling first.