ScreenshotNeo

BlogComparisons

Selenium vs Screenshot APIs for Capturing Web Pages in Bulk

Compare Selenium and hosted screenshot APIs for bulk capture, with runnable code, a practical evaluation plan, and guidance on choosing the right workflow.

By the ScreenshotNeo team4 October 202610 min read

Short answer: Use Selenium when screenshots are one step in a larger WebDriver-controlled interaction flow and your team wants to operate the browser workflow directly. Use a hosted screenshot API when a simple HTTP request and vendor-managed browser execution fit the job. Neither approach is universally faster, cheaper, or more reliable for bulk capture: decide with a representative workload and current service pricing.

Selenium’s WebDriver screenshot command captures the current browsing context, and WebDriver returns the image encoded in Base64. Hosted services expose capture through HTTP; for example, Browserless documents a screenshot endpoint that accepts a URL or HTML and options such as format, full-page capture, viewport, selector, and wait behavior. Those interfaces suggest different operational models, but they do not establish a throughput or cost winner. Selenium screenshot documentation, Browserless Screenshot API, Browserless REST API overview.

What “bulk capture” means for the decision

Bulk capture is a queue of independent page captures, often with a shared output format and viewport. The hard part is rarely issuing the screenshot command once. It is defining a valid capture, controlling concurrency, dealing with dynamic pages and failures, and operating the browser or service across the whole queue.

First define a successful result. Decide whether you need a viewport screenshot or the whole document, whether a particular element must be captured, what counts as ready, and how to identify a blank, blocked, or incomplete result. A successful HTTP response or saved PNG alone may not mean the page contains the expected content.

At a glance

Consideration Selenium / WebDriver Hosted screenshot API
Interface Browser automation commands in your application HTTP request and image response
Browser operations Your team owns browser setup, lifecycle, and execution environment The service operates browser execution; you integrate with its API
Best fit Capture is embedded in a sequence of browser interactions Capture is a discrete task that fits a request/response workflow
Capture scope Current browsing context; WebDriver also documents element screenshots Depends on endpoint options; Browserless documents full-page, selector, and clip options
Readiness Orchestrate navigation and waits in your browser workflow Use the service’s documented navigation and wait settings
Bulk capacity and cost Measure your own infrastructure and engineering costs Check current service limits and prices, then measure your workload

The table describes documented interfaces and operational responsibility, not measured comparative results. Browserless notes that lazy-loaded content may require scrolling before capture. Do not assume a full-page option alone makes every lazy image appear. Browserless screenshot options and readiness notes.

When Selenium is the better fit

  • The capture follows actions in the same browser session, such as signing in, navigating through a workflow, or changing page state.
  • Your existing system already controls browsers through WebDriver.
  • You need to own browser lifecycle, session handling, or orchestration as part of a broader automation job.
  • You can support the browser runtime and want capture to remain inside that system.

These are architectural fit signals, not claims that Selenium is more flexible or performs better for every interaction. Verify that your required browser actions and screenshot scope are supported by the driver and browser configuration you plan to run.

When a hosted screenshot API is the better fit

  • Your capture can be described as a URL, options, and an output image.
  • You want a single HTTP integration instead of managing browser execution in your application environment.
  • The API’s available options meet your requirements for format, full-page capture, viewport, selector, and waiting.
  • You prefer to keep queueing and result handling in your system while delegating browser execution to a service.

Browserless documents a REST screenshot endpoint that accepts a URL or raw HTML, an authentication token, and screenshot options, and returns image data. Its REST overview describes browser tasks exposed as HTTP requests without requiring customers to manage the browser infrastructure. This supports the managed-service description; it does not prove lower cost, higher throughput, or a service-level guarantee. Screenshot API docs, REST API overview.

Build a Selenium bulk-capture workflow

This Python example uses Selenium WebDriver to visit a list of URLs and save the current browsing context screenshot for each. Install Selenium and a compatible browser/driver setup first, then save the script as capture_bulk.py. The example deliberately runs sequentially: add concurrency only after measuring resource use and target-site behavior.

from pathlib import Path
from urllib.parse import urlparse
import re
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

URLS = [
    "https://example.com/",
    "https://www.selenium.dev/",
]
OUTPUT_DIR = Path("shots")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1440,1000")

def filename_for(url: str) -> str:
    host = urlparse(url).netloc or "page"
    safe = re.sub(r"[^A-Za-z0-9.-]+", "_", host)
    return safe + ".png"

driver = webdriver.Chrome(options=options)
try:
    for url in URLS:
        try:
            driver.set_page_load_timeout(45)
            driver.get(url)
            # Replace this with a meaningful page-specific readiness condition
            # when the page renders important content asynchronously.
            path = OUTPUT_DIR / filename_for(url)
            if not driver.save_screenshot(str(path)):
                raise RuntimeError("WebDriver did not save a screenshot")
            print(f"saved {url} -> {path}")
        except Exception as exc:
            print(f"failed {url}: {type(exc).__name__}: {exc}")
finally:
    driver.quit()

WebDriver’s screenshot operation returns a success value and saves the image through Selenium’s API. The documented protocol response is Base64 encoded; Selenium’s language binding handles that representation when using its screenshot-saving method. Selenium also documents screenshots of elements. Selenium WebDriver screenshots.

Make readiness explicit

A page-load completion signal may not mean an application has finished rendering its key content. Wait for a stable, meaningful element where possible. For example, after navigation you can wait for a page-specific selector:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# After driver.get(url):
WebDriverWait(driver, 20).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "main article"))
)

Choose a selector that indicates useful content, not just a generic document shell. For pages with lazy-loaded images, scroll in controlled increments and wait for content to settle before capturing. Scrolling changes the page state, so check that sticky headers, animations, and infinite scrolling do not alter the desired result.

Capture an element

When the target is one component instead of the page, locate it and call its screenshot method:

element = driver.find_element(By.CSS_SELECTOR, "main article")
element.screenshot("article.png")

WebDriver documents element screenshots as well as screenshots of the current browsing context. Confirm the element is visible and laid out before capture; a missing, hidden, or off-screen element can fail or produce an unexpected crop.

What to compare in a hosted API

Hosted APIs differ in request schema and supported controls. Browserless is one documented example, not a claim that every service accepts the same parameters. Review the endpoint documentation for authentication, request method, supported image formats, full-page behavior, viewport dimensions, selector or clip support, navigation timeout, wait conditions, and handling of lazy content. Browserless Screenshot API.

For a bulk system, also check service quotas, concurrency limits, request size limits, timeout behavior, retention, webhook or asynchronous job support, and current prices directly with the provider. The reviewed research does not establish these values across providers.

Evaluate both approaches on the same workload

  1. Choose representative URLs. Include ordinary pages, JavaScript-heavy pages, long pages, pages with lazy images, and authenticated pages if they occur in your queue.
  2. Fix the capture definition. Use the same viewport, scale, format, page scope, and readiness rule for both approaches.
  3. Set a success check. Verify image decoding and dimensions, then check expected visual or page-content signals. Track blank and partial captures separately.
  4. Run at realistic concurrency. Increase concurrency gradually and record queue wait, end-to-end completion time, failures, and resource use.
  5. Test retry behavior. Repeat transient failures with bounded retries and backoff. Avoid retrying permanent errors such as an invalid URL without changing the request.
  6. Compare total cost. Include service fees where applicable and the engineering and infrastructure work required to operate a Selenium fleet. Use current provider prices and actual volume.
  7. Repeat enough to see variation. One run can be affected by target-site behavior and transient network conditions; retain results by URL and failure type.

This is an evaluation method, not a benchmark. The sources reviewed provide no controlled throughput comparison, price comparison, or universal bulk-scale winner.

Bulk reliability and performance practices

Control concurrency

Start with a small number of parallel jobs and raise it while monitoring browser memory, CPU, queue delay, service limits, and target-site responses. In Selenium, each browser process and session consumes resources. With an API, concurrency is still subject to provider limits and the behavior of the sites being captured. Do not infer capacity from the fact that execution is hosted.

Bound time and retries

Set navigation and overall job deadlines. Record each URL’s attempt count, outcome, and error category. Retry transient network or service failures with a small bounded policy and backoff; send repeated failures to a review queue. A timeout may occur after the target has partially loaded, so decide whether partial images are useful or should be discarded.

Make output handling deterministic

Use a stable mapping from input item to output path or object key. Avoid collisions when different URLs share a hostname. Store enough metadata to trace the capture: requested URL, timestamp, viewport, format, capture scope, and outcome. Validate the returned bytes before marking a job complete.

Keep sessions and credentials isolated

If pages require authentication, use a controlled session and avoid sharing cookies across unrelated jobs. Keep credentials out of logs and generated filenames. Confirm how a hosted provider expects authentication data to be supplied and how it handles request data before sending sensitive pages.

Troubleshooting

Symptom Likely cause Fix
Driver cannot start Browser or driver is missing, incompatible, or unavailable in the runtime Install a compatible browser and driver, verify the runtime path and permissions, and confirm headless mode works in that environment.
Navigation hangs or times out Slow page, long-running requests, or a page that never reaches the chosen load condition Set a bounded navigation timeout; wait for a meaningful content selector when appropriate; record the URL and timeout stage.
Screenshot is blank or incomplete Capture happened before useful content appeared, the page is blocked, or the wrong context was captured Check the page title and expected selector before capture, use a content-specific wait, and inspect the page in the same environment.
Lazy images are missing Images load only when scrolled into view Scroll the relevant content into view and wait for images to load. Browserless also notes that lazy content can require scrolling before capture.
Element screenshot fails Selector matched nothing, element is hidden, or it is not ready Wait for visibility, verify the selector, and ensure the element is in a capturable layout state.
API returns an error Invalid authentication, malformed request, unsupported option, or service-side failure Check the provider’s current endpoint documentation, inspect the status and response body, and distinguish permanent request errors from transient failures before retrying.
Too many failures at higher volume Concurrency exceeds local resources, provider limits, or target-site tolerance Reduce concurrency, add queue backpressure, and compare failures by cause before increasing capacity again.
Saved file cannot be opened Error response or truncated bytes were saved as an image Check status and content type before writing; validate the image bytes and preserve error responses separately for diagnosis.

Costs and operational ownership

Selenium’s direct software interface does not make the total workflow free: account for browser hosts, scaling, monitoring, upgrades, and engineering time. A hosted API moves browser execution into a service integration, but its price, limits, and fit depend on current vendor terms and your workload. The dossier does not establish a cost winner or publish comparable prices, so calculate cost per valid capture from current pricing and measured success rates.

Reliability also has two sides: the browser/runtime and orchestration you operate with Selenium, and the service plus target-site behavior in an API workflow. Review documented guarantees and limits directly; the sources used for this comparison do not establish service-level commitments.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request returns an image or PDF. For a quick capture:

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 ScreenshotNeo API documentation for request options. The same request can be made with Python or Node.js:

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}`);
  • Cookie banners are accepted and removed before capture; the service also removes 60+ known consent platforms, newsletter popups, and chat widgets. Each step can be turned off.
  • Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed; response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
  • The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan.

Sign up for 1,000 free screenshots a month with no card.

Other browser automation options

Selenium is not the only way to control a browser directly. Playwright’s official Page API documents page screenshots and browser/page objects, so teams can consider another browser automation framework when they want to operate the browser workflow themselves. This is a brief architecture alternative, not a full framework comparison. Playwright Page API.

FAQ

Does Selenium have a bulk screenshot endpoint?

The cited Selenium documentation describes screenshots as WebDriver browser operations, including current-context and element screenshots. It does not describe a dedicated screenshot-as-a-service endpoint or a bulk throughput figure.

Is a hosted screenshot API always faster?

The researched sources do not establish that. Measure completion time and valid-capture rate on the same URLs and settings at your expected concurrency.

Can a screenshot API capture raw HTML?

Browserless documents accepting a URL or raw HTML. Other services may have different request formats, so check their endpoint documentation.

Which option should a team choose first?

Start with the workflow that matches the integration: WebDriver for a capture embedded in browser interactions, or an HTTP API for a discrete capture task. Then validate the choice with the representative evaluation above.