Screenshotlayer vs. Puppeteer: hosted screenshot API or self-hosted browser?
Compare Screenshotlayer’s hosted screenshot API with Puppeteer’s browser control, including runnable examples, costs, deployment tradeoffs, and when to choose each.
Short answer: Screenshotlayer is a hosted REST API for requesting website screenshots; Puppeteer is a JavaScript library for controlling a browser and capturing pages or elements. Choose Screenshotlayer when its managed URL-to-image endpoint, output options, quota, and concurrency fit your job. Choose Puppeteer when you need direct browser control, custom interactions, or capture logic that an API does not provide. These tools work at different layers, so the right comparison includes both feature fit and the cost of operating a browser workflow.
If you are comparing screenshot APIs, ScreenshotNeo is the first alternative to consider: it removes known consent banners, newsletter popups, and chat widgets before capture, and bills only clean shots.
1. What are Screenshotlayer and Puppeteer?
Screenshotlayer: a hosted screenshot endpoint
Screenshotlayer accepts an HTTP request containing a target URL and capture options, then returns a screenshot through its API. Its vendor documentation lists PNG, JPEG, and GIF output, with WebP advertised on paid plans. Available options include viewport dimensions, full-page capture, custom CSS and headers, delay, caching, and export to S3 or FTP on eligible plans. The specifications repository is archived, so verify exact parameter behavior against current vendor documentation before relying on a particular option.
This model avoids packaging and running the browser as part of your application. You still need to manage API credentials, quotas, response handling, retries, and the service constraints that matter to your workload.
Puppeteer: browser control from JavaScript
The Puppeteer project describes Puppeteer as a JavaScript library that provides a high-level API to control Chrome or Firefox over the DevTools Protocol or WebDriver BiDi. Its screenshot guide documents page screenshots and screenshots of selected elements. You can navigate, interact with the page, wait for application-specific conditions, and then capture the result.
The tradeoff is runtime ownership. The puppeteer package downloads a compatible Chrome during installation; puppeteer-core does not download Chrome, so your environment must provide a compatible browser. If package-manager install scripts are blocked, the browser may need to be installed manually. See the Puppeteer documentation and its screenshot guide.
2. Decision guide: which one should you use?
| Requirement | Likely fit | Reason |
|---|---|---|
| Send a URL and receive an image using a managed endpoint | Screenshotlayer | It is a hosted REST screenshot API with documented image and capture options. |
| Click through a workflow, set application state, or run custom browser logic before capture | Puppeteer | Your JavaScript code controls browser navigation and interactions. |
| Capture a page or a selected element | Either | Screenshotlayer documents full-page and viewport options; Puppeteer documents page and element screenshots. Confirm that the needed capture behavior matches your exact layout. |
| Keep the browser runtime inside your deployment boundary | Puppeteer | You choose where the browser runs, subject to the constraints of that environment. |
| Minimize browser installation and maintenance in your application | Screenshotlayer | The browser service is hosted, though you still own integration and API operations. |
| Use a published plan quota and dedicated-worker count for capacity planning | Screenshotlayer | The vendor publishes plan limits and dedicated workers; verify current terms and overages. |
| Choose based on a universal claim that one is cheaper | Neither by default | Puppeteer total cost depends on runtime, infrastructure, integration, and maintenance; the sources do not establish a universal break-even point. |
Before choosing, write down the interactions your capture requires, whether you need a viewport, full page, or element, the required format and export path, monthly volume and peak concurrent jobs, authentication and network constraints, and who will maintain the browser or API integration. Then compare the complete workload cost rather than the unit price alone.
3. Screenshotlayer: request a screenshot with cURL
Obtain an API access key through Screenshotlayer and keep it server-side. The following example requests a capture using the vendor’s access-key and target-URL pattern. Check the current API documentation for exact parameters and supported formats before adding options.
curl -G "https://api.screenshotlayer.com/api/capture" \
--data-urlencode "access_key=YOUR_ACCESS_KEY" \
--data-urlencode "url=https://example.com" \
--data-urlencode "format=PNG" \
--output screenshot.png
Screenshotlayer’s archived specification describes an endpoint and options including fullpage, width, viewport, format, css_url, delay, ttl, force, user_agent, accept_lang, and export. Treat that specification as historical reference, not current authority. Check the vendor’s pricing page and FAQ for current plan details.
For a production request, check the HTTP status and response content type before saving the body as an image. An API error response may be text or JSON rather than image bytes. Avoid logging access keys, and do not expose a private key in browser-side JavaScript.
4. Puppeteer: capture a page or element with Node.js
Install Puppeteer in a Node.js project. The regular package downloads a compatible Chrome during installation. Use puppeteer-core only when your deployment supplies and configures the browser itself.
npm install puppeteer
Save this as screenshot.mjs and run node screenshot.mjs https://example.com. It captures a full-page PNG; remove fullPage to capture the current viewport. Set SELECTOR to capture one matching element instead.
import puppeteer from 'puppeteer';
const url = process.argv[2];
if (!url) {
throw new Error('Usage: node screenshot.mjs https://example.com');
}
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 1,
});
const response = await page.goto(url, {
waitUntil: 'networkidle2',
timeout: 30_000,
});
if (!response || !response.ok()) {
throw new Error(`Navigation failed: ${response?.status() ?? 'no response'}`);
}
// For a specific element, set SELECTOR, for example: 'main article'.
const selector = process.env.SELECTOR;
if (selector) {
const element = await page.waitForSelector(selector, { timeout: 10_000 });
if (!element) throw new Error(`Element not found: ${selector}`);
await element.screenshot({ path: 'element.png' });
} else {
await page.screenshot({ path: 'page.png', fullPage: true });
}
} finally {
await browser.close();
}
networkidle2 can be unsuitable for sites that keep network connections open or continuously poll. For those pages, navigate with domcontentloaded and wait for a selector that indicates the content is ready. A full-page capture can be much taller and use more memory than a viewport capture. Puppeteer’s screenshot guide documents Page.screenshot() and ElementHandle.screenshot().
5. Code patterns for Screenshotlayer requests
Python with requests
Install the HTTP client with python -m pip install requests. The API host and route below follow the vendor’s historical specification; confirm the current endpoint and parameter names in Screenshotlayer’s live documentation before deployment.
import os
import requests
access_key = os.environ['SCREENSHOTLAYER_ACCESS_KEY']
response = requests.get(
'https://api.screenshotlayer.com/api/capture',
params={
'access_key': access_key,
'url': 'https://example.com',
'format': 'PNG',
},
timeout=90,
)
response.raise_for_status()
content_type = response.headers.get('content-type', '')
if 'image/' not in content_type:
raise RuntimeError(f'Expected image response, got {content_type!r}: {response.text[:500]}')
with open('screenshot.png', 'wb') as output:
output.write(response.content)
Node.js with fetch
This example uses the same historical API route and checks the response before writing its bytes. Keep the key in an environment variable and verify the route in current documentation.
const q = new URLSearchParams({
access_key: process.env.SCREENSHOTLAYER_ACCESS_KEY,
url: 'https://example.com',
format: 'PNG',
});
if (!process.env.SCREENSHOTLAYER_ACCESS_KEY) {
throw new Error('Set SCREENSHOTLAYER_ACCESS_KEY');
}
const res = await fetch(`https://api.screenshotlayer.com/api/capture?${q}`, {
signal: AbortSignal.timeout(90_000),
});
if (!res.ok) throw new Error(`Screenshot request failed: HTTP ${res.status}`);
const contentType = res.headers.get('content-type') ?? '';
if (!contentType.startsWith('image/')) {
throw new Error(`Expected image response, got ${contentType}: ${(await res.text()).slice(0, 500)}`);
}
await Bun.write('screenshot.png', new Uint8Array(await res.arrayBuffer()));
The Node.js example uses Bun’s file-writing helper. In a Node-only project, replace the final line with import { writeFile } from 'node:fs/promises'; await writeFile('screenshot.png', Buffer.from(await res.arrayBuffer()));.
6. Options and configuration to check
Screenshotlayer options
- Capture size: the archived specification lists
width,viewport, andfullpage. Verify dimensions, maximums, and parameter syntax in current docs. - Format: the FAQ lists PNG by default and JPEG/GIF as alternatives; pricing advertises WebP on paid plans. Confirm availability for your plan and the exact format spelling.
- Page readiness:
delayis documented in the archived specification. A fixed delay may be wasteful on fast pages and insufficient on slow pages. - Cache: the vendor says the default screenshot cache duration is 2,592,000 seconds (30 days), and that
ttlcan set a lower value. Confirm how cache bypass or refresh works before usingforce. - Page customization: documented historical options include custom CSS, user agent, and accepted language. Test them against authenticated, localized, or responsive pages.
- Export: S3 or FTP export is advertised on eligible paid plans. Check plan eligibility, credentials handling, and export behavior in current documentation.
Puppeteer options
- Browser package:
puppeteerdownloads compatible Chrome;puppeteer-coreexpects a browser supplied by the runtime. Configure the executable path and version compatibility when using a system browser. - Viewport and scale: set viewport width and height, and use
deviceScaleFactorwhen pixel density matters. Larger dimensions and scale increase image size and resource use. - Page readiness: choose an appropriate navigation wait condition, then wait for an app-specific selector or state when needed. A generic network-idle condition is not a guarantee that all visual content is ready.
- Capture scope: use page screenshots for viewport or full-page output and an element handle screenshot for a selected element. Ensure the element exists and is visible before capture.
- Browser lifecycle: close pages and browser processes in cleanup paths. In a long-running worker, define how you recover from a crashed or unresponsive browser.
7. Pricing, capacity, and total cost
Screenshotlayer’s pricing page, checked on 2026-10-03, listed these monthly plans. Prices and terms can change; confirm the current page before making a purchase.
| Vendor-listed plan | Price per month | Snapshots per month | Dedicated workers |
|---|---|---|---|
| Free | $0 | 100 | Not listed in the dossier |
| Basic | $19.99 | 10,000 | 10 |
| Professional | $59.99 | 30,000 | 20 |
| Enterprise | $149.99 | 75,000 | 40 |
The vendor describes one dedicated worker as processing one screenshot task at a time. Its FAQ says notices are sent at 75%, 90%, and 100% of the monthly request allowance and that overage charges apply. The displayed FAQ overage amounts were $0.007996 per additional Basic call, $0.0079986667 per Professional call, and $0.0079994667 per Enterprise call when checked. These are dynamic billing details; confirm the current account and pricing pages. The page also lists annual prices of $215.99, $629.99, and $1,529.99 for paid tiers and describes annual discounts up to 15%.
For Puppeteer, the available sources do not quantify total cost. Include browser compute and memory, deployment and scaling work, browser updates, monitoring, retries, storage, and engineering time in your estimate. Existing browser automation infrastructure can change the calculation substantially. Do not assume self-hosting is automatically cheaper.
For either approach, estimate average monthly captures and peak concurrency separately. Check how cache hits, retries, timeouts, and failed pages affect API usage and billed quota. A low average volume can still need more capacity if many requests arrive together.
8. Reliability, latency, and operational ownership
A hosted API shifts browser runtime operations to the service provider, but adds an external dependency and vendor-specific quotas, plan rules, and response handling. Review its current service commitments and supported authentication and navigation behavior for your use case; the reviewed materials do not establish all of those constraints.
Screenshotlayer’s FAQ claims uptime of “around 99.9%,” while also saying it does not publish public statistics and that recent reports can be requested. Attribute this figure to the vendor; it is not an independently verified measurement or a public service-level report.
With Puppeteer, you control the runtime and can tune the workflow, but your application owns browser provisioning, resource limits, process cleanup, concurrency, and recovery. Both approaches need timeouts, bounded retries for transient failures, and observability that distinguishes navigation failures from image-writing or downstream-storage failures.
9. Troubleshooting common failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Screenshotlayer returns an error document instead of an image | Invalid key, request option, quota, or upstream capture failure; code saved an error body as an image. | Check HTTP status and content type before writing the response. Inspect the error body safely, verify credentials and current parameter names, and check plan usage. |
| Screenshotlayer request uses an endpoint or parameter that no longer works | The public specification relied upon is archived. | Confirm the current endpoint and parameter syntax in live Screenshotlayer documentation; do not treat archived specifications as current service guarantees. |
| Screenshotlayer result is stale | The screenshot cache may serve a cached result; the default duration is documented as 30 days. | Check current ttl and refresh behavior, and set a shorter TTL if supported for the use case. |
| Puppeteer says Chrome executable was not found | Browser download did not run, install scripts were blocked, or puppeteer-core is used without a browser. |
Install the compatible browser or configure the executable path. Check Puppeteer’s installation documentation for the selected package and environment. |
| Puppeteer times out during navigation | The page is slow, long-lived connections prevent a network-idle condition, or the timeout is too short. | Use a suitable navigation condition such as domcontentloaded, then wait for a page-specific selector. Raise timeouts only when the workload justifies it. |
| Page screenshot is blank or missing late content | Capture ran before client-side rendering, lazy content, or fonts/images were ready. | Wait for a meaningful selector or application state. Scroll or otherwise trigger lazy content when required, and inspect the captured page state. |
| Element screenshot fails | The selector matched no element, matched too early, or the element is not visible. | Wait for the selector, verify it is unique and visible, and handle the missing-element case explicitly. |
| Worker becomes unstable under load | Too many simultaneous browser pages or large full-page captures exceed resource limits. | Bound concurrency, monitor memory and CPU, close pages and browsers in cleanup, and size workers from measured workload needs. |
10. Or skip the browser setup
ScreenshotNeo offers a hosted website screenshot API. One GET request can return a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for request options and response details.
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,
)
open("shot.webp", "wb").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}`);
- Known cookie and consent banners, newsletter popups, and chat widgets are handled before the screenshot; each cleanup step can be turned off.
- Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000. Every feature is on every plan.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
11. Frequently asked questions
Can Puppeteer call Screenshotlayer?
Yes. Puppeteer can make HTTP requests from your Node.js application, but that combines a browser-control library with a hosted API. Use that only when the workflow needs both layers.
Does Screenshotlayer replace a browser automation framework?
It replaces the capture service for jobs that fit its API. The sources do not establish that it supports every custom browser interaction your application might require; verify the behavior you need before migrating.
Can Puppeteer take an element screenshot?
Yes. Its screenshot guide documents screenshots from an element handle, in addition to page screenshots. Wait for and validate the target element before capturing.
Which one should I use for a fixed monthly volume?
Compare the current API allowance, concurrency, and overage terms with your own browser runtime and engineering costs. Volume alone does not determine the cheaper choice.
Are Screenshotlayer’s listed plans and uptime guaranteed?
The listed prices and quotas are vendor-published plan details, and the uptime figure is a vendor claim. Check current commercial terms and any service commitment directly with the provider.
Sources
- Puppeteer official site and screenshot guide.
- Screenshotlayer pricing and FAQ, checked 2026-10-03.
- Archived Screenshotlayer API specification; historical reference only.
