ScreenshotNeo

BlogComparisons

Browserless vs Puppeteer for Capturing Website Screenshots

Compare Browserless’s screenshot API with Puppeteer, see runnable examples for both, and choose the right capture workflow for your project.

By the ScreenshotNeo team4 October 20269 min read

Short answer: Use Browserless’s REST /screenshot endpoint for a one-off capture where you send a URL and receive image bytes. Use Puppeteer when your Node.js code needs to navigate, interact with the page, or control a browser before capture. You can also connect Puppeteer to a Browserless-managed browser, combining code-driven control with a hosted browser.

For a simple request-to-image workflow without managing a browser runtime, ScreenshotNeo is another option: it provides a screenshot API and MCP server, removes cookie banners, popups, and chat widgets before capture, and bills only clean shots.

1. What is the difference?

Question Browserless REST screenshot Puppeteer
What is it? A hosted browser service with an HTTP endpoint for common browser tasks. A Node.js library for automating a browser.
Who manages the browser? Browserless runs it. Your application sends a request to its endpoint. Your application launches and manages a browser, unless you connect it to a managed browser such as Browserless.
What does a basic capture look like? Send a URL or HTML and screenshot options; receive image bytes. Launch or connect to a browser, navigate or interact with a page, then call page.screenshot().
When does it fit? A stateless, one-request capture with no custom page interaction. A workflow that needs navigation, interaction, or programmatic browser control.
What does it depend on? An API token and the hosted endpoint. A working Node.js and browser environment, or a remote browser connection.

These options are not mutually exclusive. Browserless documents connecting Puppeteer to its managed browser. [Browserless screenshot API] [Puppeteer screenshot guide] [Browserless Puppeteer connection]

2. Capture a screenshot with Browserless REST

Use the current Browserless screenshot endpoint and your API token. Browserless accepts a URL or raw HTML and Puppeteer-style screenshot options, and can return PNG, JPEG, or WebP. Follow the current endpoint’s authentication and request format in its official screenshot documentation; the example below uses a JSON request body with a URL and screenshot options.

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

Keep the token out of source control. Store it in an environment variable or secret manager when running this from an application. The endpoint returns image data, so write the response to a file or stream it to the next step in your pipeline.

Useful Browserless capture controls

The documented REST endpoint supports Puppeteer-style screenshot options, including output type and full-page capture, along with request-level controls. Consult the endpoint documentation for the accepted request schema and current defaults.

  • type: PNG, JPEG, or WebP output.
  • fullPage: capture the full page rather than just the viewport.
  • clip: capture a specified rectangular region when supported by the screenshot options.
  • Selector capture: target an element instead of the whole page.
  • Viewport and wait settings: control the page dimensions and when capture begins.
  • Navigation options: adjust how navigation proceeds.
  • Resource rejection: reject selected resources where supported.
  • scrollPage: trigger lazy-loaded content before a full-page capture.

Validate option names and value formats against Browserless’s current docs, particularly if you are translating a Puppeteer configuration directly into a REST request.

3. Capture a screenshot with Puppeteer

For a local browser workflow, install Puppeteer and run a Node.js script. The official guide demonstrates launching a browser, navigating to a URL, capturing a screenshot, and closing the browser. This example saves a full-page PNG and closes the browser even if capture fails.

npm install puppeteer
// screenshot.mjs
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage({
    viewport: { width: 1440, height: 900 },
  });
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'screenshot.png', fullPage: true, type: 'png' });
} finally {
  await browser.close();
}

Run it with node screenshot.mjs. Puppeteer’s Page.screenshot() returns image data and supports saving to a path in supported environments. Its screenshot options include fullPage, clip, type, quality, and omitBackground. The documented default for fullPage is false. See the ScreenshotOptions reference.

Capture only a selected element

const card = await page.waitForSelector('.product-card');
if (!card) throw new Error('Product card was not found');
await card.screenshot({ path: 'product-card.png', type: 'png' });

Wait for the target element before taking its screenshot. If the page renders it conditionally or below the fold, make sure it is present and visible first.

Capture a clipped region

await page.screenshot({
  path: 'region.png',
  type: 'png',
  clip: { x: 120, y: 80, width: 800, height: 500 },
});

Clip coordinates are page screenshot coordinates. Ensure the requested rectangle is valid for the rendered page and viewport; use element capture when the region should follow a particular DOM element.

Capture with a transparent background or JPEG quality

// Transparent PNG where the page background permits it
await page.screenshot({ path: 'transparent.png', omitBackground: true, type: 'png' });

// JPEG quality applies to JPEG output
await page.screenshot({ path: 'compressed.jpg', type: 'jpeg', quality: 80 });

JPEG does not support transparency. Use a supported quality value for lossy output; do not rely on JPEG quality to reduce a PNG file.

4. Connect Puppeteer to Browserless

Choose this arrangement when the workflow needs Puppeteer’s code-level interaction but you want Browserless to provide the browser. Browserless documents connecting Puppeteer to a browser endpoint; use the connection URL and authentication method shown in its connection guide.

import puppeteer from 'puppeteer-core';

const browser = await puppeteer.connect({
  browserWSEndpoint: process.env.BROWSERLESS_WS_ENDPOINT,
});
try {
  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });
  await page.screenshot({ path: 'remote.png', fullPage: true });
} finally {
  await browser.close();
}

Configure BROWSERLESS_WS_ENDPOINT with the endpoint format and token required by your Browserless account. A connected remote browser is closed with browser.close() as shown in Browserless’s example. The REST route remains simpler when no interaction is needed.

5. Which should you choose?

  1. Choose Browserless REST for a single URL or HTML capture with options that fit its request schema. It keeps browser launch and lifecycle management out of your application code, while requiring an API token and hosted-service access.
  2. Choose local Puppeteer when the script must perform browser actions, inspect the page, or take multiple steps before capture, and your environment can manage the browser runtime.
  3. Choose Puppeteer connected to Browserless when you need Puppeteer’s interaction model and want a managed browser endpoint.
  4. Choose ScreenshotNeo if you want a one-call screenshot API with consent-banner, popup, and chat-widget cleanup, explicit capture verdicts, and an MCP server for AI agents.

The supplied documentation does not establish a general speed or cost winner between Browserless and Puppeteer. Compare the actual deployment requirements, service pricing, browser runtime, and capture volume for your workload rather than assuming one is faster or cheaper.

6. Screenshot behavior and edge cases

Viewport versus full page

A viewport screenshot captures the visible browser area. A full-page screenshot captures beyond that viewport. In Puppeteer, full-page mode is not the default, so set fullPage: true when needed. Browserless’s endpoint accepts Puppeteer-style options; confirm the field in the current request schema.

Lazy-loaded images and long pages

Images or sections may load only as the page scrolls. A full-page setting alone may not cause every site to load content that depends on scrolling. Browserless documents scrollPage to trigger lazy-loaded content before a full-page capture. With Puppeteer, scroll through the page or wait for the relevant content before capture, then verify that the required sections appeared.

Clipping and element screenshots

Use a clip for a known rectangle and an element screenshot for a DOM target. Element screenshots depend on the selector matching an element at capture time. Wait for the selector and handle the case where it never appears.

Bot checks and blocked pages

Automated capture can differ from a human visit when a site blocks automation. Browserless identifies blank or white captures, CAPTCHA pages, and access-denied or 403 pages as possible symptoms. Its documentation points to an /unblock API for some bot-detection cases; that is not a guarantee that every site can be captured. [Browserless screenshot documentation]

7. Troubleshooting

Symptom Likely cause What to try
Unauthorized or rejected request Missing, invalid, or incorrectly placed Browserless token. Check the endpoint’s required authentication format and confirm the token is available to the process. Avoid printing it in logs.
Response is not an image The request failed or returned an error response that was saved as a file. Inspect the HTTP status and response content type before treating the body as image bytes. Log a redacted error body for diagnosis.
Blank or white screenshot The page did not render as expected, navigation did not complete, or the site blocks automation. Check the response and page state, try an appropriate wait condition, and determine whether the site presents a CAPTCHA or access-denied page. Browserless’s unblock API may help with some cases, not all.
Capture happens before content appears The page is still loading data or rendering content when capture starts. Wait for a specific selector or use an appropriate navigation wait strategy. Prefer a meaningful page condition over an arbitrary long delay.
Images are missing on a full-page capture Images load lazily after scrolling or are delayed by the site. Trigger scrolling before capture, use Browserless’s documented scrollPage option, and wait for the expected images or sections.
Selector capture times out or fails The selector is wrong, the element is conditional, or it never becomes visible. Verify the selector in the page, wait for it explicitly, and handle the missing-element case.
Screenshot is only the viewport Full-page capture was not enabled. Set Puppeteer’s fullPage: true or the equivalent supported Browserless screenshot option.
Puppeteer cannot launch locally The browser runtime or its environment is unavailable or misconfigured. Check Puppeteer installation and runtime requirements for the deployment environment; consider connecting to a managed browser if local browser management is unsuitable.
Remote Puppeteer connection fails The WebSocket endpoint or authentication does not match the account configuration. Use the endpoint format and credentials in the Browserless connection docs, and check network access to that endpoint.

8. Performance, reliability, and cost

There is no comparable benchmark in the cited materials, so request latency, throughput, and price should be measured against your own target sites and deployment. A one-request REST flow avoids application-side browser lifecycle code, while local Puppeteer makes the application responsible for launching, closing, and operating the browser. A managed Puppeteer connection moves browser hosting to Browserless but still leaves your script responsible for navigation and interactions.

  • Control capture duration: set practical navigation and wait behavior for the page; pages with long-running network requests can otherwise delay a capture.
  • Keep browser lifecycles bounded: close locally launched browsers in a finally block and clean up remote connections after use.
  • Limit output size: viewport captures are often smaller than full-page captures; select image format and JPEG quality to suit the downstream use.
  • Handle failures explicitly: distinguish transport errors, service errors, blocked-page results, and valid image responses before storing output.
  • Calculate service cost from current terms: Browserless usage pricing is not established by this comparison’s research. Include API or managed-browser charges and operational browser costs in your own estimate.

9. Or skip the browser setup

If you need a screenshot without building a browser workflow, ScreenshotNeo’s API takes a URL in one GET request and returns a screenshot or PDF. Here is a cURL example:

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

Equivalent 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)

Equivalent 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}`);
if (!res.ok) throw new Error(`ScreenshotNeo returned HTTP ${res.status}`);
await Bun.write('shot.webp', res);

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

10. FAQ

Can Browserless take a screenshot from HTML instead of a URL?

Yes. Its screenshot endpoint accepts a URL or raw HTML; check the current API documentation for the HTML request field and options.

Can I get WebP from Browserless?

Yes. Browserless documents PNG, JPEG, and WebP output formats.

Is Puppeteer only for screenshots?

No. It is a browser automation library. Screenshot capture is one capability, and code can navigate or interact with a page before capturing.

Will Browserless’s unblock API solve every CAPTCHA?

No. The documentation describes it for some bot-detection cases, not as a universal way around every CAPTCHA or access restriction.

Sources