ScreenshotNeo

BlogComparisons

Puppeteer Screenshot Alternatives for Node.js Website Capture

Compare Node.js screenshot options: run Puppeteer or Playwright yourself, use a hosted capture API, or send one URL to ScreenshotNeo.

By the ScreenshotNeo team4 October 202611 min read

If you need website screenshots from Node.js, the main alternatives to running Puppeteer locally are Playwright, a hosted browser such as Browserless, and a screenshot API such as ScreenshotNeo or ScreenshotOne. Choose a browser library when you need to control page interaction and browser behavior. Choose a hosted service when you want to submit a URL without operating browser infrastructure. ScreenshotNeo is the alternative to try first when you want a one-call capture, clean screenshots, and billing that excludes failed or unclean captures.

There is no evidence in the sources reviewed for a universal fastest or highest-quality option. The practical choice depends on how much browser control you need, whether you want to run browsers yourself, and which capture features and service terms fit your use case.

Quick comparison

Option Best fit What you operate What to check
ScreenshotNeo Capture a URL with one HTTP request, with options such as full-page, selector, waits, custom headers, and formats. Your request and API key; browser execution is handled by the service. Choose the needed output and capture options. Only clean shots are billed; response headers identify the page verdict and billing status.
Playwright Browser automation where navigation, interactions, and capture belong in a Node.js workflow. Browser setup and execution unless you connect to a remote browser. Confirm the browser and screenshot features your workflow needs. The research reviewed here does not establish a complete feature comparison with Puppeteer.
Browserless Use a hosted screenshot endpoint or connect Puppeteer/Playwright to a remote browser. A hosted browser session and your client integration. Check current service limits, availability, and commercial terms. Its docs describe full-page and element capture, waits, and navigation controls.
ScreenshotOne Use a hosted URL-to-image API from Node.js, with its SDK or HTTP requests. Your request and API credentials. Verify current pricing and limits. Its page advertises 100 free screenshots a month; this vendor offer can change.
Local Puppeteer Keep browser execution under your control and use Puppeteer’s documented page and element screenshot flows. Browser installation, runtime, and operations. Account for browser lifecycle, resource use, page readiness, and failure handling.

Hosted services trade some infrastructure ownership for a service dependency. Running browser automation yourself gives you control over the environment, while leaving browser setup and operations with your team. That is an architectural tradeoff, not a claim about total cost or performance.

Option 1: Use Playwright for a code-first browser workflow

Playwright is a browser automation library that can fit a Node.js workflow where you need to navigate and interact with pages before capturing them. The research reviewed here documents Browserless connections for Playwright, but does not provide enough evidence for a full feature-by-feature comparison against Puppeteer. Check the official Playwright documentation for current installation and screenshot APIs before adopting it.

For screenshots that only need a URL and a file, an automation library may involve more browser lifecycle work than a hosted screenshot request. If your task includes page interactions or browser-driven checks, retaining browser automation may be the right shape; if you only need an image from a URL, compare hosted APIs as well.

Option 2: Keep Puppeteer and move browser execution to Browserless

Switching away from local Puppeteer does not require abandoning the Puppeteer programming model. Browserless documents connecting puppeteer-core over WebSocket to a remote browser. This keeps navigation and screenshot calls in Node.js while the browser runs remotely. Browserless also documents a REST screenshot endpoint, including full-page and element capture, waits, and navigation controls.

The code below shows the local Puppeteer pattern. For remote execution, use Browserless’s current connection endpoint and authentication format from its documentation; those values are account-specific and are not included here.

import puppeteer from 'puppeteer';

const url = process.argv[2] ?? 'https://example.com';
const browser = await puppeteer.launch({ headless: true });

try {
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle2', timeout: 45_000 });
  await page.screenshot({ path: 'page.png', fullPage: true, type: 'png' });
} finally {
  await browser.close();
}

Run it with node capture.mjs https://example.com after installing Puppeteer in the project. The source documentation’s basic flow is to launch a browser, navigate with a readiness condition, capture, and close. Use puppeteer-core when you connect to a browser supplied elsewhere, following the provider’s documented connection setup.

Option 3: Use Puppeteer’s screenshot controls directly

If Puppeteer already fits the job, its screenshot options cover common output needs. For a specific element, locate the element and use ElementHandle.screenshot(); Puppeteer documents scrolling a hidden target into view before capture.

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
try {
  const page = await browser.newPage();
  await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
  await page.goto('https://example.com', { waitUntil: 'networkidle2', timeout: 45_000 });

  // Full-page PNG
  await page.screenshot({ path: 'full.png', fullPage: true, type: 'png' });

  // Element screenshot (replace with a selector present on the target page)
  const card = await page.$('.product-card');
  if (!card) throw new Error('Could not find .product-card');
  await card.screenshot({ path: 'card.png', type: 'png' });

  // JPEG region capture; quality applies to JPEG, not PNG
  await page.screenshot({
    path: 'region.jpg',
    type: 'jpeg',
    quality: 85,
    clip: { x: 0, y: 0, width: 900, height: 600 }
  });

  // Transparent background, useful for pages that support transparency
  await page.screenshot({ path: 'transparent.png', omitBackground: true, type: 'png' });
} finally {
  await browser.close();
}

Install Puppeteer with npm install puppeteer and save the example as an ES module such as capture.mjs. Puppeteer’s documented options include fullPage, clip, omitBackground, path, quality, and type. Quality does not apply to PNG. For current option details, consult the official Puppeteer guide and screenshot option reference.

Option 4: Submit a URL to a hosted screenshot API

A hosted screenshot API is a better fit when you want a URL-to-image request and do not need to manage browser launch and shutdown in your application. Browserless documents a REST POST /screenshot endpoint. ScreenshotOne documents a Node.js SDK and an HTTP request workflow. Verify service limits, request formats, and commercial terms with each vendor before production use.

For ScreenshotNeo, send a GET request to the API base with an access key and target URL. The example below saves the response body to a WebP file. Put the key in an environment variable in a real application rather than committing it to source control.

cURL

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,
)
r.raise_for_status()
with open("shot.webp", "wb") as f:
    f.write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: process.env.SCREENSHOTNEO_API_KEY,
  url: 'https://stripe.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
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 and response details. The API supports PNG, JPEG, WebP, or PDF output, and the ScreenshotNeo parameter names used by other screenshot APIs also work, which can make migration easier.

Choosing the right capture approach

Use a browser library when

  • You need to drive interactions or make decisions based on page state before capturing.
  • You want browser execution in an environment your team operates.
  • Your capture is one step in a broader browser automation workflow.

Use a remote browser when

  • You want Puppeteer or Playwright calls but prefer to outsource browser execution.
  • You need the browser library’s navigation and capture workflow with a remote endpoint.
  • You have confirmed the provider’s current session limits and commercial terms.

Use a screenshot API when

  • The input is primarily a URL and the output is an image or PDF.
  • You want to avoid managing a local browser installation and lifecycle.
  • Its waits, selectors, headers, cookies, and output controls match the target page.

ScreenshotNeo is the first API to try when clean page captures and predictable billing matter: it accepts cookie banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; only clean shots are billed; and the paid plans start at $5 for 3,000 screenshots. These are product facts, not comparative benchmark claims.

Capture details that affect the result

Full page versus viewport

A viewport screenshot captures the visible browser area. A full-page screenshot extends to the document’s page height. Long pages may contain lazy-loaded images that are only requested as the user scrolls, so ensure the chosen method loads them before taking the capture. ScreenshotNeo supports full-page capture with lazy images loaded.

Element versus region

Use an element screenshot when you need a component such as a card or chart. In Puppeteer, select the element and use its screenshot method; missing selectors should be handled as an explicit error. Use a clip rectangle when the target is a known page region. Browserless documents both selector-based element capture and clip regions.

Format and transparency

Choose PNG for lossless output, JPEG when a lossy image is suitable, or WebP where your downstream consumers support it. Puppeteer documents output type and quality controls; quality applies to JPEG, not PNG. Transparent background capture requires omitBackground and only produces useful transparency when the page background can be omitted.

Readiness and waits

Navigation completion does not always mean the page has finished rendering the content you care about. Wait for a meaningful selector, a suitable delay, or network idle based on the site. Avoid an arbitrary long delay when a selector can signal readiness. If the page continuously polls or streams, network idle may never occur; use a selector or bounded delay instead.

Authentication and locale

Authenticated or localized pages may require cookies, headers, authorization, user agent, timezone, or geolocation. ScreenshotNeo supports these request controls, along with custom CSS and JavaScript, click-before-capture, selector hiding, request/resource blocking, dark mode, device presets, viewport sizing, and retina scale. It also supports PDF settings including paper size, margins, landscape orientation, and page ranges.

Or skip the browser setup

Send one URL to ScreenshotNeo and save the returned image:

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

See the API docs for options. 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 screenshot tools. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for the free plan.

Cost, performance, and reliability considerations

Cost

For self-hosted browser automation, account for the compute and engineering time to install, launch, monitor, and update browsers. For hosted services, check current pricing, included usage, overages, and limits; those terms may change. ScreenshotNeo’s stated plans are Free: 1,000 shots/month with no card; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; and Business: $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Only clean shots are billed; bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Each response identifies its page verdict and billing status in X-Page-Verdict and X-Billed headers.

Performance

No comparative timing benchmark is established by the sources. Capture time depends on the target page, readiness condition, image loading, and whether browser execution is local or remote. Reduce unnecessary waits, avoid capturing more page area than needed, and select an output format appropriate to its use. Measure your own representative URLs and concurrency patterns before setting a service-level expectation.

Reliability

Browser capture depends on third-party page behavior, which can include slow scripts, bot checks, consent dialogs, and pages that never become idle. Use bounded navigation and request timeouts, a selector-based readiness check where possible, and explicit error handling. For production pipelines, record the target URL, request options, response status, and service verdict/billing headers. Hosted capture adds a vendor dependency; self-hosting adds responsibility for browser and runtime operations.

Troubleshooting

Symptom Likely cause Fix
Screenshot is blank or mostly empty Capture occurred before the page rendered, or navigation failed. Wait for a visible target selector or a bounded delay; inspect the response or browser navigation error before treating the image as valid.
Navigation hangs until timeout The page keeps network activity open, or the chosen readiness condition is too strict. Use a selector or bounded delay instead of network idle for streaming/polling pages; set a finite timeout.
Element screenshot fails because the element is missing The selector is wrong, the element is conditional, or it has not appeared yet. Check the selector against the rendered page, wait for it, and handle a missing element explicitly.
Element is present but capture is clipped or invisible The target may be outside the viewport or hidden. Scroll it into view and verify visibility before capturing. Puppeteer documents scrolling hidden targets into view for element screenshots.
Full-page image omits images lower down Images are lazy-loaded only after scrolling. Use a method that loads lazy images before full-page capture, or explicitly scroll through the page before capturing.
PNG ignores the quality setting Puppeteer quality does not apply to PNG output. Use JPEG when lossy quality control is required, or keep PNG for lossless output.
Transparent screenshot still has a background The page background is painted by page content or transparency was not enabled. Use Puppeteer’s omitBackground option and ensure page styling does not draw an opaque background.
Hosted request returns an error or unexpected body Authentication, parameter encoding, target URL, or provider limits may be wrong. Check the provider’s current request documentation, encode the target URL correctly, verify credentials, and inspect status/headers before writing the response as an image.
Bot check or CAPTCHA appears The destination is challenging automated traffic. Do not assume a screenshot tool can bypass access controls. Check the site’s permitted access path. ScreenshotNeo identifies bot checks/CAPTCHAs as unclean outcomes that are not billed.

Migration checklist

  1. Inventory required behavior: full page, element, clipping, authentication, custom viewport, output type, and any interaction before capture.
  2. Decide whether your application needs browser control or only URL-to-file capture.
  3. Test representative pages, including a long lazy-loaded page, a page with consent UI, an authenticated page if relevant, and a page with slow or persistent network activity.
  4. Set explicit timeouts and readiness conditions; handle failed navigation and missing selectors.
  5. Validate the resulting dimensions, format, and transparency in the downstream consumer.
  6. For hosted tools, verify current service limits, commercial terms, data handling, and request options before rollout.
  7. Track failures and, where supplied, verdict and billing headers so retries and cost accounting use actual outcomes.

FAQ

Is Playwright a drop-in replacement for Puppeteer?

Both are browser automation approaches, but the research reviewed here does not establish a complete feature comparison or guarantee drop-in compatibility. Check the APIs and behavior your scripts rely on before switching.

Can I keep Puppeteer while using a hosted browser?

Yes. Browserless documents connecting Puppeteer Core to a remote browser over WebSocket, so the application can retain a Puppeteer workflow while the browser runs remotely.

When should I use a screenshot API instead of browser automation?

Use an API when the task is primarily submitting a URL and receiving an image or PDF. Use browser automation when your code needs to drive the page or make decisions during the session.

Does ScreenshotOne have a free allowance?

Its reviewed Node.js page advertises 100 free screenshots per month. Treat that as a vendor offer and verify it before relying on it.