ScreenshotNeo

BlogComparisons

Is Browserless Worth It for Screenshot APIs? Review and Use Cases

Browserless turns a POST request into a rendered screenshot. Here’s how its API, metering, and use cases affect whether it fits your workload.

By the ScreenshotNeo team4 October 202612 min read

Short answer: Browserless can be worth it when you need a managed browser for stateless screenshot jobs and prefer an HTTP request over maintaining browser infrastructure. Its REST screenshot endpoint can render a URL or supplied HTML and return image bytes. The cost depends on browser time, concurrency, proxy traffic, and CAPTCHA solving, so the plan price alone cannot tell you the cost per screenshot. Test it against your actual pages before choosing a paid tier.

Screenshot API to try first: ScreenshotNeo. It removes cookie banners, popups, and chat widgets before capture, bills only clean shots, and has a paid plan starting at $5 for 3,000 screenshots. A Browserless evaluation still makes sense if you specifically need its managed browser interface or want to compare a browser-session workflow.

What Browserless’s screenshot API does

The current Browserless REST screenshot endpoint is POST /screenshot. Authenticate with an API token in the token query parameter, send JSON containing a target url and optional screenshot options, and save the returned binary response as an image. The documented output formats are PNG, JPEG, and WebP. The REST API handles a browser task per request; it does not require you to install Puppeteer or Playwright locally. See the current screenshot API reference and REST API overview.

For a new integration, use the current endpoint and documentation. The BaaS v1 screenshot page is deprecated.

Quick start: capture a URL

First create a Browserless account and obtain an API token from its dashboard. Keep the token on the server or in a secret manager; do not expose it in browser-side JavaScript, a public repository, or a client application. The examples below use the documented San Francisco endpoint. Replace the placeholder token with your own.

cURL

curl --fail-with-body -sS -X POST \
  "https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE" \
  -H "Cache-Control: no-cache" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/",
    "options": {
      "fullPage": true,
      "type": "png"
    }
  }' \
  --output screenshot.png

--fail-with-body makes cURL report an HTTP error instead of silently treating an error response as an image. Check the output file type if an integration returns an unexpected response.

Python

Install the dependency with python -m pip install requests. Save this as screenshot.py and run python screenshot.py.

import requests

TOKEN = "YOUR_API_TOKEN_HERE"
endpoint = "https://production-sfo.browserless.io/screenshot"
payload = {
    "url": "https://example.com/",
    "options": {
        "fullPage": True,
        "type": "png",
    },
}

response = requests.post(
    endpoint,
    params={"token": TOKEN},
    headers={"Cache-Control": "no-cache"},
    json=payload,
    timeout=90,
)
response.raise_for_status()

content_type = response.headers.get("content-type", "")
if not content_type.startswith("image/"):
    raise RuntimeError(f"Expected image bytes, got {content_type}: {response.text[:500]}")

with open("screenshot.png", "wb") as image_file:
    image_file.write(response.content)
print("Saved screenshot.png")

Node.js

This example uses the built-in fetch API available in current Node.js releases. Save as screenshot.mjs and run node screenshot.mjs.

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

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 response = await fetch(endpoint, {
  method: "POST",
  headers: {
    "Cache-Control": "no-cache",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    url: "https://example.com/",
    options: { fullPage: true, type: "png" },
  }),
  signal: AbortSignal.timeout(90_000),
});

if (!response.ok) {
  throw new Error(`Browserless HTTP ${response.status}: ${await response.text()}`);
}
const contentType = response.headers.get("content-type") ?? "";
if (!contentType.startsWith("image/")) {
  throw new Error(`Expected image bytes, got ${contentType}`);
}
await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer()));
console.log("Saved screenshot.png");

Screenshot options and request configuration

Browserless accepts Puppeteer-style screenshot settings in the options object. The following are the principal capture controls documented for this API. Confirm the current API schema for the complete supported shape and any option-specific constraints.

Need Setting Notes
Whole page options.fullPage: true Captures beyond the visible viewport. Pair with scrolling when the page lazy-loads content.
Image format options.type PNG, JPEG, or WebP are documented. Match the extension and downstream decoder to the actual format.
JPEG quality options.quality Use with lossy formats where supported; quality is not meaningful for lossless PNG.
Viewport options viewport dimensions Set the viewport to the CSS-pixel dimensions your layout should render at.
Retina or scale options.deviceScaleFactor Changes the pixel density of the output and can increase image size.
Fixed region options.clip Specify an x, y, width, and height rectangle.
One element Top-level selector Place alongside url, not inside options. The service waits for the selected element and captures its bounds.
Wait for content Shared wait configuration Wait for a selector, timeout, event, or function when the page needs extra time to render.
Navigation behavior gotoOptions Configure page navigation, including the load event to wait for. Waiting for network idle can hang on pages with persistent requests.
Lazy-loaded content scrollPage: true Scroll before capture to trigger content that appears only when brought into view; combine with full-page capture as needed.
Inject styling or scripts addStyleTag, addScriptTag Supply inline content or a URL to modify page presentation or behavior before the capture.
Block unwanted network activity rejectResourceTypes, rejectRequestPattern Can reduce unnecessary resource work, but blocking a required font, image, or script can change the rendered result.
Continue after selected wait failures bestAttempt Allows the capture to proceed when asynchronous wait conditions fail or time out; inspect the resulting image rather than assuming it is complete.

For example, a selected-element capture can be requested with a top-level selector:

{
  "url": "https://example.com/",
  "selector": "main article",
  "options": { "type": "webp" }
}

For a fixed viewport crop instead, put a clip rectangle inside options. Use an element selector when the target moves with the layout; use a fixed clip when the coordinates are part of the capture specification.

Inline HTML instead of a URL

To render markup supplied by your application, send an html field and omit url. Browserless explicitly warns not to include both in one request.

curl --fail-with-body -sS -X POST \
  "https://production-sfo.browserless.io/screenshot?token=YOUR_API_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<html><body><h1>Rendered report</h1></body></html>",
    "options": { "fullPage": true, "type": "png" }
  }' \
  --output report.png

When rendering HTML, account for external assets and fonts: the browser must be able to load them, and an inline document may not share the origin or authentication state of your normal application.

Browser launch settings and proxies

Shared launch parameters apply to REST calls and can be passed as query parameters or as a URL-encoded JSON launch payload. When both forms are used, individual query parameters take precedence over matching values in the launch object. Refer to Browserless launch parameters for supported values and the full configuration syntax.

Proxy settings can route a request through Browserless’s built-in residential or datacenter proxy pools. The current documentation lists residential traffic at 6 units per MB and datacenter traffic at 2 units per MB; built-in proxy bandwidth is charged on top of browser time. Third-party proxies are configured separately and do not consume Browserless proxy units according to its proxy documentation. Use a proxy only when your target, geography, or access policy requires it, and confirm you are authorized to access the page.

Browserless documents /unblock as an option for some bot-detection cases. It is not a guarantee that a protected page will render, and CAPTCHA-solving or proxy use affects cost. Prefer the ordinary screenshot endpoint for pages that allow normal browser rendering; evaluate protected pages individually.

When Browserless fits—and when it may not

Good fits

  • Scheduled snapshots of public pages, internal reports, and dashboards that your service is permitted to access.
  • Full-page or selected-element images for documentation, visual monitoring, or an image-processing pipeline.
  • Rendering generated HTML into an image without deploying a browser runtime yourself.
  • An event-driven service that can make one HTTP request and store or process the returned bytes.

These are use-case conclusions from documented API capabilities, not results of independent testing.

Look at another interface or deployment when

  • The workflow is interactive or branching. A REST request is designed for one browser task. If the workflow must inspect state, react, and choose the next action, Browserless points to browser connections or function execution as alternatives. Its BrowserQL screenshot examples also show a declarative option.
  • You need infrastructure control. Browserless documents cloud and self-hosted options; a self-managed browser stack may better fit your requirements when deployment control is a priority.
  • Targets block automation or vary heavily. Test each important target. A screenshot may show a CAPTCHA, access-denied page, blank page, or incomplete content instead of the expected page.
  • Cost has to be predictable per image. Browser-time units round up in 30-second increments, and proxy or successful CAPTCHA usage can add charges. Measure real requests before estimating.

Is Browserless worth the price?

Browserless’s current pricing page lists a free allowance of 1,000 units per month, a Prototyping plan at $25 per month billed annually for 20,000 units, Starter at $140 per month billed annually for 180,000 units, and Scale at $350 per month billed annually for 500,000 units. It also lists plan-specific concurrency, session-duration, and overage terms. These are live commercial terms and can change; check the current Browserless pricing page before making a purchase decision.

A unit is up to 30 seconds of browser session time. Partial increments round up, so 31 seconds consumes two time units. The same metering applies to REST requests. Browserless’s unit consumption documentation also lists built-in residential proxies at 6 units per MB, datacenter proxies at 2 units per MB, and successful CAPTCHA solves at 10 units each.

Cost driver What to measure Why it matters
Browser time Elapsed session duration, including navigation and waits Each partial 30-second increment rounds up.
Proxy traffic Proxy type and megabytes transferred Built-in proxy traffic adds usage beyond browser time.
CAPTCHA solving Successful solves per capture Each successful solve adds 10 units.
Peak concurrency Maximum simultaneous captures and queueing Plan concurrency caps can reject or delay work even if monthly units remain.
Failures and retries Time spent before failure and retry policy A mid-run failure can still use browser-time and proxy units; repeated retries can multiply consumption.

To estimate your monthly need, run representative captures across the page types you care about. Record elapsed time, image correctness, timeouts, proxy bytes, and retry frequency. Multiply measured usage by expected monthly volume, then account for concurrency peaks and the live plan’s overage rules. Browserless does not publish a universally applicable cost per screenshot, and the dossier establishes no comparative cost, latency, or success-rate benchmark.

Compare that estimate with the engineering time and operating burden of running your own browser infrastructure. A low-volume proof of concept can exercise the free allowance. For production, evaluate page correctness, failure behavior, concurrency and limits, data handling and geography requirements, as well as the resulting bill.

Performance and reliability practices

  • Choose the smallest sufficient capture. Viewport images usually involve less page area and output data than full-page images. Use JPEG or WebP where their tradeoffs suit your downstream use.
  • Wait for a meaningful condition. A selector or application-specific readiness signal is often more useful than an arbitrary long delay. Network-idle waits can be unsuitable for pages with polling, streaming, or persistent connections.
  • Trigger lazy loading deliberately. Enable page scrolling for content loaded on scroll, and verify the bottom of long pages rather than assuming full-page mode triggered every asset.
  • Set bounded timeouts. Give navigation and the overall HTTP call a limit based on the target and workflow. A timeout prevents a caller from waiting indefinitely, but it does not mean a request that already used browser time was free.
  • Keep concurrency inside the account limit. Queue or throttle work on your side, inspect rejected requests and concurrency in the dashboard, and avoid retrying a capacity rejection immediately in a tight loop.
  • Retry selectively. Retry transient transport errors and selected server errors with a small bounded exponential backoff and jitter. Do not blindly retry validation errors, authorization failures, or a page that consistently blocks automation.
  • Validate bytes and results. Check HTTP status and content type before saving. For important jobs, inspect image dimensions or use visual checks to detect blank, partial, or challenge-page captures.
  • Protect credentials and images. Keep the API token server-side. Treat screenshots as potentially sensitive output, and apply your own access controls and retention rules.

Troubleshooting Browserless screenshots

Symptom Likely cause What to do
HTTP 401 or 403 from the API Missing, invalid, or misrouted token; authentication is sent in the wrong place. Use the current endpoint and pass the token as the documented token query parameter. Rotate a token if it has been exposed.
HTTP error or JSON saved with a .png suffix The request failed, but the client wrote the response body as though it were image bytes. Check status before writing; log the error body safely and confirm the Content-Type.
Blank or nearly blank screenshot The page has not rendered, navigation failed, or automation was blocked. Check the target in a normal browser, configure an appropriate wait, and inspect for a CAPTCHA or access-denied page. Evaluate the documented /unblock option for applicable cases.
Missing images or content lower on the page Assets load lazily only when scrolled into view. Use scrollPage: true with full-page capture, then verify the output.
Text or layout differs from an expected screenshot Viewport, device scale factor, font availability, locale, or load timing differs. Set a consistent viewport and scale, wait for the needed content, and ensure external fonts and assets can load.
Element selector returns no useful capture The selector does not match, appears late, or identifies a container with unexpected bounds. Check the selector against the rendered DOM, wait for it to appear, and inspect element dimensions. Use a clip rectangle for a fixed region.
Request hangs or exceeds the client timeout Slow navigation, an overly strict wait, persistent network activity, or an unbounded client request. Use a suitable navigation event or selector wait, set client and page timeouts, and avoid network-idle waits on pages that never become idle.
429, rejected request, or queued work Concurrency cap or plan allowance reached. Queue and limit parallel requests, check plan limits and dashboard usage, and adjust the plan only if measured demand requires it.
Unexpectedly high usage Sessions cross 30-second boundaries, retries repeat work, or proxy/CAPTCHA usage adds units. Measure time per capture, reduce unnecessary waits, avoid unconditional proxies and retries, and review the usage dashboard.
Inline HTML request fails or ignores markup Both html and url were provided, or the inline page’s assets cannot load. Send one input mode only and check access to external resources.

Or skip the browser setup

ScreenshotNeo offers a one-call screenshot API. Its documentation covers the request options. This example saves the response as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp
import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as image_file:
    image_file.write(r.content)
const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`ScreenshotNeo HTTP ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(({ writeFile }) => writeFile('shot.webp', bytes));
  • Cookie banners are accepted and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the shot; each step can be turned off.
  • Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Responses report the page verdict and billing status in headers.
  • An MCP server gives AI agents tools for screenshots, page information, and PDF capture.
  • The free plan includes 1,000 screenshots a month with no card. Paid plans start at $5 for 3,000 screenshots.

Sign up free for ScreenshotNeo: 1,000 screenshots a month, no card required.

FAQ

Does the screenshot endpoint return an image URL?

No. The documented response is image bytes. Save the response body to a file or send it directly to your image-processing pipeline.

Can I use the same request to render supplied HTML and navigate to a website?

No. Choose either html or url; the current documentation warns against sending both together.

Does using Browserless mean every protected site will work?

No. Bot-detection tools and proxies are technical options, not a guarantee. Some targets can still deny access or return a challenge page.

Is Browserless proven faster or cheaper than another screenshot API?

The available research provides no independent latency, success-rate, or cost-per-capture comparison. Run the same representative workload through the candidates you are considering.

Should I use the deprecated v1 endpoint for an existing integration?

For new work, follow the current REST screenshot API documentation. If you maintain a v1 integration, review the deprecation notice and plan a migration against the current endpoint before relying on legacy behavior.