ScreenshotNeo

BlogHow-to

How to Capture Mobile-Width Website Screenshots with Browserless for Indian Clients

Capture a client site at mobile CSS width with Browserless. Choose viewport or full-page output, configure emulation and waits, then check the image for blocked or missing content.

By the ScreenshotNeo team4 October 20269 min read

To capture a website at mobile width with Browserless, send a POST request to its /screenshot REST endpoint with your API token, the target URL, and a viewport width in CSS pixels. Add mobile emulation settings only when you need mobile browser behavior as well as a narrow responsive layout. Choose a viewport, full-page capture, clip, or selector according to what the client needs to see, and inspect the returned image for blocked or missing content.

This workflow produces a browser-emulated screenshot. It does not establish how the site looks on a real Indian handset or network, and the available Browserless documentation does not establish India-specific pricing, data residency, privacy obligations, or service availability.

1. Get a Browserless token and make a screenshot request

Create or retrieve an API token in your Browserless account dashboard. The REST screenshot API uses POST /screenshot, accepts JSON, and returns an image. Keep the token private: use an environment variable or secret manager, and never commit a real token or include it in client-facing examples. See the Browserless Screenshot API documentation for the endpoint’s current request schema and response details.

Here is a minimal cURL request. Replace the placeholder token and target URL. The example saves the response as PNG; confirm the format option supported by the endpoint version you use.

export BROWSERLESS_TOKEN='YOUR_API_TOKEN'
curl --fail-with-body \
  -X POST "https://production-sfo.browserless.io/screenshot?token=${BROWSERLESS_TOKEN}" \
  -H 'Content-Type: application/json' \
  --data '{
    "url": "https://example.com",
    "options": {
      "type": "png",
      "fullPage": false,
      "viewport": {
        "width": 390,
        "height": 844,
        "deviceScaleFactor": 1,
        "isMobile": true,
        "hasTouch": true
      }
    }
  }' \
  --output screenshot.png

Browserless documents token authentication and image responses, but its exact host and supported options can depend on the Browserless product or deployment you use. Use the host and schema shown in your account and the endpoint reference. Do not assume that a successful HTTP response proves the target page rendered correctly.

2. Set the mobile viewport correctly

Set viewport.width and viewport.height in CSS pixels before capture. Responsive breakpoints are evaluated against the rendered viewport width, so use the width that answers the client’s question. For example, a width of 390 means a 390 CSS-pixel browser layout viewport; it is not by itself a claim that the page was tested on a particular phone.

Setting Use it for What to keep in mind
width, height Controlling the responsive layout and visible viewport Choose CSS-pixel dimensions that match the review brief. Height affects what is initially visible, not the responsive width.
deviceScaleFactor Changing raster pixel density The output image can have more physical pixels than the CSS viewport. State CSS dimensions and raster dimensions separately when reporting results.
isMobile Enabling mobile-oriented browser behavior A narrow viewport alone changes responsive layout; emulation adds browser behavior. It still is not a real-device test.
hasTouch Making touch capability available to the page Useful for pages that change controls or behavior based on touch support.
isLandscape Emulating landscape orientation where supported Set dimensions and orientation consistently; verify the actual returned image.

Browserless also documents OS emulation, including Android. Use it when the review requires a mobile operating-system identity or behavior, and consult the OS emulation documentation for the supported configuration. A viewport plus mobile flags is often sufficient for responsive design review; do not add emulation fields without a reason.

3. Choose the capture boundary

Use the output boundary that matches the deliverable. A normal viewport screenshot records the visible initial screen at your chosen width. fullPage aims to capture the full document height. A clip captures a fixed rectangle, while a selector capture waits for an element and crops to its bounding box.

Need Approach Trade-off
Show the first screen as a visitor sees it Viewport capture; fullPage: false Content below the viewport is not included.
Review the whole long page fullPage: true Long pages can take longer and may include content that loads only after scrolling.
Capture a known rectangular region clip Coordinates and dimensions must correspond to the rendered page.
Capture one component, such as a product card Selector option The element must exist and be visible; selector capture waits for it and uses its bounding box.

Browserless’s screenshot mutation reference describes selector and clip capture options. Check the exact request shape for the REST endpoint you’re calling in the screenshot mutation reference; similar concepts can have different JSON shapes across Browserless APIs.

4. Wait for the page state you need

Immediate capture can miss content rendered after navigation, including images, client-side components, and lazy-loaded sections. Browserless supports waiting for events, functions, selectors, or timeouts. Prefer a wait tied to the content needed for the screenshot over an arbitrary long delay. For a long page with lazy-loaded images, Browserless recommends combining page scrolling with full-page capture so scrolling can trigger lazy loading; see its Screenshot API guidance.

  • Wait for a stable page event when the document is still loading.
  • Wait for a specific selector when a key component must be present.
  • Use a short timeout only when the site has no reliable readiness signal.
  • For lazy content, enable the endpoint’s page-scrolling option together with full-page capture, if supported by the request schema.
  • Inspect the saved image for missing images, loading placeholders, overlays, and content that appeared too late.

Do not treat a wait as a guarantee that all third-party content has finished. Ads, analytics, personalization, and asynchronous requests may continue or fail independently.

5. Complete runnable examples

The following examples show the request pattern, token handling, mobile-width viewport, and saving the returned image bytes. Confirm the Browserless host and option schema for your account. The API reference is authoritative for supported fields.

Python

import os
import requests

TOKEN = os.environ["BROWSERLESS_TOKEN"]
endpoint = "https://production-sfo.browserless.io/screenshot"
payload = {
    "url": "https://example.com",
    "options": {
        "type": "png",
        "fullPage": False,
        "viewport": {
            "width": 390,
            "height": 844,
            "deviceScaleFactor": 1,
            "isMobile": True,
            "hasTouch": True,
        },
    },
}
response = requests.post(
    endpoint,
    params={"token": TOKEN},
    json=payload,
    timeout=90,
)
response.raise_for_status()
content_type = response.headers.get("content-type", "")
if "image/" not in content_type:
    raise RuntimeError(f"Expected an image response, got {content_type!r}: {response.text[:500]}")
with open("screenshot.png", "wb") as output:
    output.write(response.content)
print(f"Saved {len(response.content)} bytes to screenshot.png")

Node.js

const token = process.env.BROWSERLESS_TOKEN;
if (!token) throw new Error('Set BROWSERLESS_TOKEN first');

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

const payload = {
  url: 'https://example.com',
  options: {
    type: 'png',
    fullPage: false,
    viewport: {
      width: 390,
      height: 844,
      deviceScaleFactor: 1,
      isMobile: true,
      hasTouch: true,
    },
  },
};

const response = await fetch(endpoint, {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify(payload),
  signal: AbortSignal.timeout(90_000),
});
if (!response.ok) {
  throw new Error(`Browserless returned HTTP ${response.status}: ${(await response.text()).slice(0, 500)}`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.startsWith('image/')) {
  throw new Error(`Expected an image response, got ${contentType}: ${(await response.text()).slice(0, 500)}`);
}
const image = Buffer.from(await response.arrayBuffer());
const { writeFile } = await import('node:fs/promises');
await writeFile('screenshot.png', image);
console.log(`Saved ${image.length} bytes to screenshot.png`);

For the same task without managing a browser capture request, ScreenshotNeo provides a screenshot API and MCP server. Its parameter names also work with those used by other screenshot APIs, which can make migration simpler. See the ScreenshotNeo documentation for the current request options.

6. Or skip the browser setup

ScreenshotNeo can return a screenshot from one GET request. This example saves a WebP response for a mobile-width viewport; consult the API documentation for the current options and response behavior.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com --data-urlencode viewport_width=390 --data-urlencode viewport_height=844 -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", "viewport_width": 390, "viewport_height": 844}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com', viewport_width: '390', viewport_height: '844' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
  • Cookie banners, newsletter popups, and chat widgets are removed before capture; each cleanup step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers report the page verdict and billing status.
  • An MCP server lets AI agents, including Claude and Cursor, take screenshots with tools for screenshots, page information, and PDF capture.
  • 1,000 screenshots per month are free with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free 1,000 screenshots a month, with no card required.

7. Troubleshooting Browserless captures

Symptom Likely cause What to do
401 or 403 response from the API Missing, invalid, expired, or incorrectly passed token; wrong endpoint host Check the account token, endpoint host, and documented query parameter. Keep credentials out of logs and source control.
Request fails or returns an error document Invalid JSON, unsupported option, or wrong schema for the API variant Read the response body safely, validate JSON, and compare each field with the exact endpoint documentation.
Blank or mostly white image Page not ready, navigation failure, automation blocking, or application rendering issue Check the URL independently, add a relevant wait, and inspect the image. Browserless identifies blank captures as a possible sign of automation blocking.
CAPTCHA or access-denied page The target site may block automated browsing Report the result as a blocked capture. Browserless documents an /unblock API, but it is not a guarantee for a particular site.
Mobile layout still looks like desktop Viewport was not applied before navigation/capture, wrong request nesting, or the site has no breakpoint at that width Confirm the viewport fields and dimensions in the endpoint schema, then inspect the page at that CSS width. Browserless guidance emphasizes setting viewport before capture.
Image dimensions differ from the requested CSS dimensions Device scale factor changes raster pixel density; full-page capture changes height Distinguish CSS viewport dimensions from output raster dimensions and check the selected scale factor and capture boundary.
Images or lower sections are missing Lazy-loaded content was not triggered or page was captured too early Wait for the needed content and use page scrolling with full-page capture where the API supports it.
Selector capture is empty or incomplete Selector did not match, matched a hidden element, or layout had not stabilized Use a selector that uniquely identifies the visible element, wait for it, and confirm its bounding box in the rendered page.

8. Reliability, performance, and cost

Capture time depends on navigation, page behavior, waiting, scrolling, and the amount of content rendered. Full-page and lazy-content captures do more work than a simple viewport capture. Use the smallest capture boundary and the specific readiness condition that meet the brief, and set a client-appropriate request timeout. Retry only transient request failures with a bounded policy; repeating a deterministic CAPTCHA or invalid request is unlikely to help.

For repeatable client delivery, record the requested URL, CSS viewport, emulation fields, capture type, wait condition, timestamp, and whether the image visibly contains the expected page. Treat the output as a browser rendering at configured dimensions, not evidence of a real device, Indian carrier, or regional network result. The collected Browserless documentation provides no verified performance benchmark, India-specific pricing, data-residency claim, or local availability claim; check current account terms and the client’s requirements directly before making those commitments.

9. FAQ

Is a 390-pixel screenshot proof the site works on an Indian phone?

No. It is a browser capture using a configured CSS viewport and optional emulation. Real handset, browser, carrier, and regional network testing require separate checks.

Should I always enable mobile emulation?

No. Set the viewport width for responsive layout. Add mobile properties when touch or mobile-specific browser behavior is part of the question.

Can Browserless guarantee it will capture a site that blocks automation?

No. A CAPTCHA, blank page, 403, or access-denied screen can indicate blocking. Browserless documents an unblock endpoint, but its success on a specific target is not established by the available guidance.

Which output should I send a client?

Send a viewport image for the initial-screen review, or full-page output when they need the whole document. Label the CSS viewport and any emulation used so the image’s scope is clear.