Browserless vs Apify for Website Screenshots in India
Choose based on what “in India” means: India-based proxy egress, India-hosted browser compute, or data residency. Compare Browserless, Apify Actors, and ScreenshotNeo by workflow, controls, and workload cost.
“In India” can mean three different things: the browser runs on compute physically located in India, the request reaches the website through an India-based proxy IP, or the captured data must meet an India data-residency requirement. These are not interchangeable. The reviewed Browserless regional endpoint page lists San Francisco, London, and Amsterdam, while Browserless documents country-targeted proxies. The reviewed Apify sources establish proxy capabilities but do not establish an India browser-compute region. Confirm the exact requirement and current vendor commitment before choosing either service.
Quick choice: ScreenshotNeo is the first alternative to consider for a straightforward screenshot API: one GET returns an image or PDF, clean-up options handle common banners and widgets, and only clean shots are billed. Choose Browserless when you want a browser service with a direct screenshot endpoint or Puppeteer/Playwright connections. Choose an Apify Store Actor when its specific batch, storage, and run workflow fits your job. Neither the proxy sources nor the reviewed region list prove that screenshot compute runs in India.
1. Decide what “in India” requires
| Requirement | What it means | What to verify |
|---|---|---|
| India proxy egress | The target website sees a request routed through an India exit IP. | Country coverage for the proxy type, Actor compatibility, and observed exit IP for the actual capture. |
| India-hosted browser compute | The browser process itself runs in an India data center. | A named India region or written provider confirmation. A proxy exit in India does not establish this. |
| India data residency | Browser traffic, screenshots, logs, and stored files are handled under a required location policy. | Where each data category is processed and retained, including logs, temporary files, and Actor storage. |
Browserless documents proxyCountry for residential or datacenter proxy routes. Its reviewed regional endpoint listing names US West (San Francisco), London, and Amsterdam, not India. That describes the reviewed page, not a guarantee that no private deployment or later-added region exists; ask the vendor if compute location matters. Apify Proxy supports datacenter and residential proxy types, but a given screenshot Actor must expose or support the needed proxy configuration. See Browserless proxy options, Browserless regions, and Apify Proxy documentation.
2. How the workflows differ
Browserless: screenshot endpoint or connected browser
Browserless offers a direct POST /screenshot REST endpoint. Send a URL and screenshot options; the response is an image. Its documented options include PNG, JPEG, and WebP, viewport or full-page capture, viewport/device scale settings, clipping, and element selection. Use this path for a capture that can be expressed as one HTTP request.
When you must navigate through multiple steps, interact with a page, or manage custom waits, Browserless also supports hosted browser connections from Puppeteer or Playwright. Close the browser session when finished so it does not keep consuming browser time. The REST and browser-connection approaches are documented in the Screenshot API guide and connection examples.
Apify: choose a specific Store Actor
Apify screenshot capture is typically a Store Actor workflow, not one universal screenshot endpoint with one shared option set or price. Each Actor defines its own input schema, output records, supported formats, batching, proxy controls, error handling, and billing. Read the chosen Actor’s input, output, and pricing sections before integrating it.
For a concrete example, the Reestri Website Screenshot and PDF Actor describes batches of public pages, PNG/JPEG/WebP/PDF, viewport or full-page capture, element selection, and device presets. Its listing says failed URLs are not charged. Those are terms of that Actor, not Apify-wide guarantees. Another Actor may bill differently or expose different controls.
3. Capture controls and output
| Need | Browserless | Apify | Implementation note |
|---|---|---|---|
| Image formats | PNG, JPEG, WebP documented for screenshot API. | Depends on Actor; Reestri lists PNG, JPEG, WebP, and PDF. | Confirm quality/compression controls and maximum dimensions on the actual endpoint. |
| Full page or viewport | Both modes documented. | Actor-specific; Reestri documents both. | Very long pages can hit pixel-height or image-format limits. Check output dimensions and truncation indicators. |
| Element or region | Selector or fixed clip options documented. | Actor-specific; Reestri captures the first selector match. | Wait for the target element; selectors can be absent, duplicated, or hidden responsively. |
| Responsive/device capture | Set viewport and device scale factor; exact preset behavior depends on the integration. | Actor-specific; Reestri lists desktop, tablet, and mobile presets. | Use explicit dimensions and scale where pixel output consistency matters. |
| Dynamic and lazy content | REST options and browser connections support different levels of waiting/control. | Actor-specific; Reestri lists wait conditions and optional scroll-to-bottom behavior. | Prefer a meaningful selector wait over an arbitrary long delay when the page has a reliable ready element. |
| Batching and orchestration | REST calls or your own browser workflow. | Actor run model and limits vary; Reestri listing documents batch capture. | Check concurrency, per-run caps, output retrieval, retry semantics, and retention. |
For Browserless, selector is supplied at the top level of the request body, while Puppeteer-style screenshot settings go in options. The API documentation also describes scrollPage for triggering lazy loading before a full-page capture. For Apify, do not assume another Actor shares Reestri’s limits or behavior; use the selected Actor’s live schema.
4. Runnable Browserless examples
These examples use the documented Browserless screenshot endpoint. Set BROWSERLESS_TOKEN in your environment and replace the target URL as needed. The API token is in the query string, so keep it out of source control, browser-side code, and logs.
cURL
curl -X POST \
"https://production-sfo.browserless.io/screenshot?token=$BROWSERLESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com/","options":{"fullPage":true,"type":"png"}}' \
--output screenshot.png
Python
import os
import requests
endpoint = "https://production-sfo.browserless.io/screenshot"
response = requests.post(
endpoint,
params={"token": os.environ["BROWSERLESS_TOKEN"]},
json={
"url": "https://example.com/",
"options": {"fullPage": True, "type": "png"},
},
timeout=90,
)
response.raise_for_status()
with open("screenshot.png", "wb") as image:
image.write(response.content)
Node.js
import { writeFile } from "node:fs/promises";
const endpoint = new URL("https://production-sfo.browserless.io/screenshot");
endpoint.searchParams.set("token", process.env.BROWSERLESS_TOKEN);
const response = await fetch(endpoint, {
method: "POST",
headers: { "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 returned ${response.status}: ${await response.text()}`);
}
await writeFile("screenshot.png", Buffer.from(await response.arrayBuffer()));
For an India proxy exit, add documented proxy parameters to the request URL, for example proxy=residential&proxyCountry=in. Residential proxy traffic is listed at 6 units/MB and datacenter at 2 units/MB. Datacenter coverage spans fewer countries; Browserless says to use residential when a country lacks datacenter coverage. These parameters select egress routing, not browser compute location. See the proxy documentation.
5. Apify Actor integration: API pattern and verification
Apify API calls run a particular Actor and pass that Actor’s input. The exact input object and output dataset fields vary. The snippet below shows the general synchronous run-and-fetch pattern; set ACTOR_ID to the Actor you selected and replace the input with its documented schema. It is not a universal screenshot schema.
cURL pattern
curl -X POST \
"https://api.apify.com/v2/acts/$ACTOR_ID/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"urls":["https://example.com/"]}'
Python pattern
import os
import requests
actor_id = os.environ["ACTOR_ID"] # Use the ID of the chosen Store Actor
url = f"https://api.apify.com/v2/acts/{actor_id}/run-sync-get-dataset-items"
response = requests.post(
url,
params={"token": os.environ["APIFY_TOKEN"]},
json={"urls": ["https://example.com/"]}, # Replace with this Actor's input schema
timeout=300,
)
response.raise_for_status()
items = response.json()
print(items)
Node.js pattern
const actorId = process.env.ACTOR_ID; // ID of the chosen Store Actor
const endpoint = new URL(`https://api.apify.com/v2/acts/${actorId}/run-sync-get-dataset-items`);
endpoint.searchParams.set("token", process.env.APIFY_TOKEN);
const response = await fetch(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ urls: ["https://example.com/"] }), // Actor-specific input
signal: AbortSignal.timeout(300_000),
});
if (!response.ok) throw new Error(`Apify returned ${response.status}: ${await response.text()}`);
console.log(await response.json());
Before production, verify the Actor’s accepted input keys, maximum URLs, concurrency, output format, dataset or key-value-store retrieval, proxy support, and event/platform charges. The synchronous endpoint is convenient for short runs; for larger workloads use the Actor run lifecycle and retrieve its results after completion rather than assuming every run fits a single HTTP request.
6. Cost: estimate the workload, not the headline
Browserless units
Browserless meters browser session time in 30-second increments: each started 30-second period costs one unit. Built-in proxy traffic is additional: 6 units per MB for residential, 2 units per MB for datacenter. A successful CAPTCHA solve costs 10 units. A failed request can still consume units if a browser session started or proxy traffic was transferred. The current pricing page lists Free at 1,000 units/month, Prototyping at $25/month billed annually with 20,000 units, Starter at $140/month billed annually with 180,000 units, and Scale at $350/month billed annually with 500,000 units; overage rates vary by tier. Prices and allowances can change, so check the current Browserless pricing page and unit-consumption documentation.
Estimate monthly Browserless units as: captures × browser-time units per capture + proxy MB × proxy units per MB + successful CAPTCHA solves × 10. Base browser time rounds up in 30-second periods. Measure representative pages and include retries and longer waits in the estimate; a slow page can cross a billing boundary.
Apify Actor and platform charges
Apify cost depends on the selected Actor. Some Actors charge per event; some may also incur platform usage. For example, the Reestri listing shows $2 per 1,000 viewport/element screenshots and $4 per 1,000 full-page screenshots or PDFs, plus an Actor start charge. Its listing says browser compute is included in those event prices, but storage remains subject to Apify storage and retention terms. Another listing, Nefes Tools, gives different event prices and a start charge. These examples demonstrate why “Apify screenshot price” is not one fixed number.
Estimate: runs × start charge + each event type × its listed event price + platform usage (if applicable) + proxy + retained storage. Include retries and the chosen Actor’s exact rules for failed, blocked, or stored results. Apify says most pay-per-event Actors include platform usage, while some bill it separately; read the Apify pricing documentation and the chosen Actor listing.
Compare equivalent work
- Count monthly URLs and captures per URL, including viewport variants.
- Separate viewport, full-page, element, and PDF jobs.
- Measure page weight, average duration, and retry rate on representative targets.
- Add India proxy routing only where required; account for transfer and proxy pricing.
- Include storage duration, download/transfer, and scheduled-run overhead.
- Compare the total monthly estimate at your expected volume, then pilot near the expected peak concurrency.
7. India-specific selection guide
| If your priority is… | Start with… | Why / caveat |
|---|---|---|
| A clean, direct screenshot call with straightforward billing | ScreenshotNeo | GET API returns PNG, JPEG, WebP, or PDF; common consent banners, popups, and chat widgets can be removed before capture, and only clean shots are billed. |
| Browser API plus an existing Puppeteer or Playwright workflow | Browserless | It offers a screenshot REST endpoint and hosted browser connections. Budget by browser time and proxy use. |
| Ready-made batch/run workflow from a Store | A specific Apify Actor | Actor inputs, batch limits, result storage, and charges differ. Select and validate the exact Actor. |
| India proxy egress | Browserless proxy or compatible Apify proxy setup | Confirm India country support and actual egress for the route you will run. Proxy geography does not identify compute geography. |
| India compute location or data residency | Neither based on the reviewed evidence alone | Obtain current provider confirmation for the exact region and data categories before committing. |
For any service, take a small proposed pilot with pages that represent your real targets: Indian-language pages, pages that redirect by locale, pages with consent layers, a long lazy-loaded page, and any site that may challenge automation. Record the requested URL, final URL, status/title, output dimensions, whether the expected content appears, retries, and billed usage. This is an evaluation checklist, not a claim that either vendor was tested for this article.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP, or PDF. Use this call for a basic capture; see the ScreenshotNeo API documentation for the API and its options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are never billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. Start with 1,000 free screenshots a month, no card required.
9. Troubleshooting
| Symptom | Likely cause | What to do |
|---|---|---|
| Browserless returns an authentication or validation error | Missing/invalid token, wrong endpoint, or malformed JSON. | Check the token, method, endpoint region, and JSON shape; keep token out of logs. Validate that options is an object. |
| Browserless runs out of units faster than expected | Long sessions round up by 30 seconds; proxy bandwidth and successful CAPTCHA solves also consume units. | Close connected browser sessions promptly, set sensible timeouts, measure page transfer, and include proxy and solve costs in the estimate. |
| Requested India routing is not observed | Country coverage differs by proxy type, or an Actor does not support the supplied proxy settings. | Check the provider’s supported countries and the selected Actor inputs; verify observed egress. Use residential when Browserless datacenter coverage does not include the country. |
| Screenshot misses lazy images or below-fold content | Content loads only on scroll or after a page-specific event. | Enable the endpoint’s documented scroll-before-capture behavior or use a browser connection/Actor option that scrolls; wait for a known element before capture. |
| Selector capture is empty or times out | Selector does not match, appears late, is in a frame, or is hidden at that viewport. | Inspect the selector in the rendered page, wait for visibility, choose the intended viewport, and handle iframe content with a browser workflow if needed. |
| Apify run succeeds but some URLs failed | Actor runs can complete while individual URL records contain errors. | Inspect per-item status and error fields, not just the run status. Apply the Actor’s retry guidance only to transient failures. |
| Apify result is missing after a run | Output may be in a dataset or key-value store, and temporary storage follows retention rules. | Read the Actor’s output instructions, fetch the correct dataset/store, and copy assets to durable storage if needed. |
| Long full-page output is truncated | Actor height cap or image dimension/format limit. | Check output metadata and the Actor’s maximum height. Split the page, use PDF, or choose a suitable format when supported. |
| Different runs produce different pixels | Dynamic content, animations, fonts, locale, viewport, or timing varied. | Fix viewport/device scale and locale; wait for a stable page element; disable motion with supported custom CSS or use a fixed capture window. |
10. Performance and reliability practices
- Set finite network and navigation timeouts. Long waits cost Browserless units and can consume Actor run budget.
- Use bounded concurrency. More simultaneous captures can increase queueing and target-site rate limiting; test the peak you expect.
- Prefer a selector wait or the narrowest useful readiness condition. A network-idle condition can stall on pages with persistent requests.
- Use viewport captures when a full page is unnecessary; they reduce output size and often avoid very tall-image limits.
- Choose JPEG or WebP for smaller photographic output when supported and acceptable; choose PNG for lossless UI detail. Confirm quality controls for the chosen endpoint/Actor.
- Retry transient DNS/network/browser failures with a limit and backoff. Do not blindly retry deterministic 4xx responses, selector errors, or bot challenges.
- For repeated pages, check caching behavior and freshness requirements. ScreenshotNeo supports caller-selected cache TTL; account for cache hits in its billing behavior.
- For public web captures, respect site access rules and avoid sending secrets in URLs or custom headers unless the workflow and storage policy are appropriate.
11. FAQ
Does an India proxy mean the screenshot is processed in India?
No. It describes the network exit used for the target request. Compute and data residency need separate confirmation.
Is Apify’s screenshot price always $2 per 1,000?
No. That is a starting price shown for one specific Actor and event type. Other Actors have their own event and platform charges.
Which should I choose for a one-off screenshot?
Use a direct screenshot API when you need one capture with few moving parts. Browserless and ScreenshotNeo both provide a direct HTTP screenshot route; compare the required cleanup, billing, and output behavior.
Can either service guarantee a screenshot of every public website?
No guarantee is established by the cited documentation. Public pages can fail, change behavior, or present bot checks. Pilot the actual targets and inspect each result.
Can I use a screenshot service with an AI agent?
Apify workflows can be integrated through its platform and MCP tooling; ScreenshotNeo provides an MCP server with screenshot, page-info, and PDF tools. Check the respective tool’s inputs and output handling for your client.
