ScreenshotNeo

BlogComparisons

ScreenshotOne vs Selenium for Scheduled Webpage Captures

Compare a hosted screenshot API with Selenium for recurring webpage captures, including scheduling, runnable code, operations, and costs.

By the ScreenshotNeo team4 October 202612 min read

Short answer: Neither ScreenshotOne nor Selenium supplies the recurring schedule described here. Your cron service, CI workflow, or other scheduler must start each capture. ScreenshotOne is a hosted capture API that avoids operating the browser stack; Selenium is browser automation you control, suited to workflows that need scripted interaction, browser selection, or control over the execution environment. These are recommendations based on documented capabilities, not comparative test results.

For a managed screenshot service to try first, ScreenshotNeo provides one-call captures, removes known consent banners, popups, and chat widgets before capture, and bills only clean shots. The rest of this guide compares ScreenshotOne and Selenium on their own terms, then shows how to schedule each.

1. What is actually being scheduled?

A scheduled capture has four separate parts:

  1. Trigger: runs at a time or interval, such as a system cron job or a CI schedule.
  2. Capture worker: calls an API or starts a Selenium browser session.
  3. Output handling: names and stores the image, PDF, or metadata.
  4. Operations: protects credentials, handles failures, prevents unwanted overlap, and records results.

The reviewed official documentation establishes no recurring scheduler built into ScreenshotOne or Selenium. ScreenshotOne’s asynchronous mode and webhooks change how a request completes; they do not schedule the next run. Selenium Grid distributes WebDriver work to remote browser instances; it also does not define the schedule. Keep the timer in the job runner you already operate.

2. ScreenshotOne vs Selenium at a glance

Question ScreenshotOne Selenium
What is it? A hosted API for capturing a URL, HTML, or Markdown. A browser automation framework with WebDriver bindings and browser-specific implementations.
Who operates rendering? The API provider operates browser rendering. You operate the browser and driver locally, or run remote browsers through Grid.
Interaction before capture Capture options include selectors, waits, scripts, and styles. Validate complex multi-step interactions against current API capabilities. Script navigation and browser interactions directly.
Browser control Viewport and device emulation options; emulation is not a physical device. Control browser sessions and, through Grid, route work across configured browser versions, operating systems, and machines.
Recurring scheduling External scheduler required. External scheduler required.
Cost evidence This research does not establish current comparative pricing. This research does not establish the cost of operating your browser infrastructure.
Speed and reliability evidence No common workload benchmark was conducted. No common workload benchmark was conducted.

ScreenshotOne is a plausible low-operations choice for recurring captures that use standard viewport, full-page, or output-format controls. Selenium is a plausible choice when the capture depends on browser actions, specific browser versions, or a test-suite-like cross-browser matrix. These are inferences from documented capabilities, not claims about which is faster, cheaper, or more reliable.

Primary references: ScreenshotOne options, ScreenshotOne getting started, Selenium WebDriver, and Selenium Grid.

3. Set up the recurring job first

Choose a runner that already fits your deployment and make its scheduled command invoke a single capture program. Keep the schedule independent of the capture implementation so you can change API or browser later.

  1. Pick the timezone and cadence explicitly; many schedulers interpret schedules in UTC or a configured timezone.
  2. Decide what to do if a run is still active when the next trigger fires: skip, queue, or allow parallel captures. For snapshots of the same URL, skipping or queueing usually avoids races over output filenames.
  3. Set a maximum job duration. The runner’s timeout must exceed the expected capture time and allow output storage.
  4. Keep API keys and other secrets in the runner’s secret store or environment, not in the script or repository.
  5. Write outputs with a timestamp or deterministic run identifier, and log the URL, start time, result, and failure category.
  6. Define retry behavior. Retry transient transport or service errors with bounded backoff; avoid retrying every failure, especially invalid URLs, bad credentials, and persistent target-side blocks.

This is scheduler-agnostic: use the scheduled-trigger feature in your existing platform. The research does not establish limits or syntax for a particular cron, CI, or cloud scheduler, so check that scheduler’s own documentation.

4. Do-it-yourself: scheduled Selenium screenshot

Selenium makes the browser session part of your worker. Install the Python binding and make a browser available. Selenium Manager can help manage drivers when using supported current Selenium setups; otherwise install a matching browser driver as required by your environment. See the Selenium installation guide and browser driver guide.

python -m venv .venv
. .venv/bin/activate
python -m pip install selenium

Save this as capture.py. It opens a page, waits for document readiness plus an optional target selector, captures a PNG, and always closes the browser. Tune the explicit wait to the page’s real readiness signal; a fixed sleep is simpler but wastes time and can still be too short.

import os
from pathlib import Path
from datetime import datetime, timezone

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait

URL = os.environ.get("CAPTURE_URL", "https://example.com")
OUTPUT_DIR = Path(os.environ.get("CAPTURE_DIR", "captures"))
READY_SELECTOR = os.environ.get("READY_SELECTOR")  # e.g. main .report

OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
output = OUTPUT_DIR / f"capture-{stamp}.png"

options = Options()
options.add_argument("--headless")
options.add_argument("--window-size=1440,1000")
# Add --no-sandbox only when required by your container setup and threat model.

driver = webdriver.Chrome(options=options)
try:
    driver.set_page_load_timeout(45)
    driver.get(URL)
    WebDriverWait(driver, 20).until(
        lambda d: d.execute_script("return document.readyState") == "complete"
    )
    if READY_SELECTOR:
        WebDriverWait(driver, 20).until(
            lambda d: d.find_element("css selector", READY_SELECTOR).is_displayed()
        )
    if not driver.save_screenshot(str(output)):
        raise RuntimeError("WebDriver did not save the screenshot")
    print(output)
finally:
    driver.quit()

Run it once manually before connecting it to a schedule:

CAPTURE_URL="https://example.com" python capture.py

For an element screenshot, find the element and call element.screenshot("element.png"). For example:

from selenium.webdriver.common.by import By

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

Selenium screenshot methods capture the current browsing context or an element; full-page behavior varies by browser and driver. If you need a stitched full-page image, verify that your chosen browser workflow supports it instead of assuming a viewport screenshot includes content below the fold. Selenium’s official examples cover screenshot support in its WebDriver documentation.

Schedule the Selenium script

Configure your chosen scheduler to run python /absolute/path/capture.py. Use an absolute working directory and ensure the scheduled environment has the same virtual environment, browser packages, fonts, permissions, timezone, and environment variables as the manual run. For containerized execution, include a browser and its required system libraries in the image.

For remote execution, point Selenium’s Remote WebDriver client at a private Selenium Grid endpoint and configure desired browser capabilities. Grid can route scripts to remote browser instances and support parallel or cross-platform execution. Protect the Grid endpoint with appropriate network controls: Selenium warns that exposed Grid instances can permit third-party access to internal applications or execution of binaries. See Grid documentation and Grid setup.

5. Do-it-yourself: scheduled ScreenshotOne API capture

Create a ScreenshotOne API key and store it as a secret. Its API supports GET and POST; the key can be supplied as a query parameter, in POST JSON, or through the X-Access-Key header. Always use HTTPS. The examples below use the documented GET style and save the response bytes as a PNG.

cURL

curl --fail --silent --show-error -G "https://api.screenshotone.com/take" \
  -H "X-Access-Key: ${SCREENSHOTONE_ACCESS_KEY}" \
  --data-urlencode "url=https://example.com" \
  --data-urlencode "format=png" \
  --data-urlencode "viewport_width=1440" \
  --data-urlencode "viewport_height=1000" \
  --output capture.png

Python

import os
import requests

key = os.environ["SCREENSHOTONE_ACCESS_KEY"]
response = requests.get(
    "https://api.screenshotone.com/take",
    headers={"X-Access-Key": key},
    params={
        "url": "https://example.com",
        "format": "png",
        "viewport_width": 1440,
        "viewport_height": 1000,
    },
    timeout=100,
)
response.raise_for_status()
with open("capture.png", "wb") as file:
    file.write(response.content)

Node.js

import { writeFile } from "node:fs/promises";

const params = new URLSearchParams({
  url: "https://example.com",
  format: "png",
  viewport_width: "1440",
  viewport_height: "1000",
});
const response = await fetch(`https://api.screenshotone.com/take?${params}`, {
  headers: { "X-Access-Key": process.env.SCREENSHOTONE_ACCESS_KEY },
  signal: AbortSignal.timeout(100_000),
});
if (!response.ok) {
  throw new Error(`ScreenshotOne returned ${response.status}: ${await response.text()}`);
}
await writeFile("capture.png", Buffer.from(await response.arrayBuffer()));

See the ScreenshotOne documentation for current option names and limits. The current options documentation lists a 60-second default and 90-second maximum request timeout, plus a 30-second default and maximum navigation timeout. Set your client timeout with room for network overhead, and don’t assume increasing a client timeout increases the API’s own maximum.

6. Capture options that affect recurring results

Keep the screenshot specification identical from run to run unless a change is intentional. For ScreenshotOne, relevant documented controls include:

  • Input and output: URL, HTML, or Markdown input; common image formats and PDF, plus HTML or Markdown response modes.
  • Page area: viewport dimensions, device emulation, full-page capture, and a CSS selector for a single element.
  • Readiness: wait conditions, wait for selector, delay, navigation timeout, and overall timeout. Prefer a meaningful selector/readiness condition over arbitrary long delays.
  • Rendering changes: custom scripts and styles, device emulation, and viewport configuration.
  • Request context: custom headers and credentials where appropriate. Avoid logging secrets or placing sensitive tokens in publicly visible URLs.
  • Async delivery: async execution with a webhook for results. Your scheduler still initiates each recurring run, and your receiver should validate webhook authenticity if configured.
  • Bulk work: the bulk endpoint wraps regular capture requests. The docs caution that it shares a one-minute request bucket and that execution is lazy unless execute=true; do not treat a submitted bulk request as proof that all images are rendered. Check its documented constraints before adopting it.

For larger HTML or Markdown inputs, use POST JSON rather than placing large values in a URL. The API documentation lists a 100 MiB maximum POST body. See options, requests and responses, and bulk screenshots.

For Selenium, the effective configuration includes browser and driver versions, headless mode, window size, locale/timezone where configured, page-load and script timeouts, readiness waits, and any authentication state or browser actions. Pin the environment to avoid accidental visual changes after browser or dependency updates. Do not mix implicit and explicit waits without understanding their combined timing behavior; explicit waits around the exact readiness condition are easier to reason about.

7. Reliability, performance, and cost

Reliability

  • Record whether each run produced a usable file, not just whether the scheduler command exited successfully.
  • Use bounded retries with backoff for transient network or service failures. A retry should use a distinct attempt identifier and must not silently overwrite a known-good previous capture.
  • Prevent overlapping jobs from writing the same filename. Use a lock, queue, unique timestamp, or scheduler concurrency setting.
  • Monitor repeated empty, challenge, or error pages. A successful HTTP response or browser navigation does not guarantee the page content is the intended one.
  • Retain enough metadata to reproduce a capture: target URL, UTC timestamp, viewport, format, browser/API version context, and relevant options.

Performance

Large pages, animations, third-party scripts, and unnecessary wait delays add work. Capture only the required area when possible, wait for a specific ready element, and avoid excessive parallelism. Selenium Grid can distribute sessions, but practical capacity depends on the Grid deployment. ScreenshotOne’s bulk endpoint shares its documented request bucket with ordinary captures. No cross-product speed benchmark is available from this research; pilot with your target pages and cadence if latency determines the architecture.

Cost

Compare the complete operating cost, not only an API request price: scheduled-run compute, browser image maintenance, Grid hosting and monitoring, storage, and engineering time all matter. Current comparative ScreenshotOne pricing and Selenium infrastructure costs were not established in the research, so calculate them from current vendor terms and your own deployment. Do not infer comparative cost from feature pages alone.

8. Troubleshooting

Symptom Likely cause Fix
Selenium cannot start the browser Browser/driver mismatch, missing browser libraries, permissions, or an environment difference in the scheduler. Run the script in the scheduler’s actual image/user; install a compatible browser and driver or use Selenium Manager where supported; inspect driver logs.
Screenshot is blank or incomplete Capture happened before client rendering, images, or a target component became ready. Wait for document state and a page-specific selector; increase a bounded explicit wait; check lazy-loaded content and scroll behavior.
Navigation hangs The site keeps network connections open, stalls, or exceeds configured page-load time. Set a page-load timeout, wait for a more suitable readiness condition, and confirm the page is reachable from the worker environment.
ScreenshotOne returns an access-key error Missing, invalid, rotated, or wrong-organization key. Check the key and organization, update the scheduler secret, and never print the key in logs. See API key guidance.
ScreenshotOne timeout error The target is slow, the delay is too large, or rendering cannot complete within the request timeout. Reduce page weight or delay, tune wait_until, timeout, or navigation_timeout within documented limits, or use async/webhook for longer work where supported. See timeout troubleshooting.
Bulk call returns before all captures exist Bulk execution is lazy unless explicitly requested. Use execute=true if immediate execution is required, account for the shared request bucket, and wait for completion.
Scheduled job runs twice or misses a slot Scheduler retry, overlapping execution, timezone mismatch, or runner downtime. Use an idempotent output key, set an overlap policy, log scheduled and actual start times, and define how missed runs are handled.
Works locally but not in CI/cron Different PATH, current directory, secret configuration, browser dependencies, network rules, or timezone. Use absolute paths, declare the working directory and timezone, verify secrets are injected, and run the same command under the scheduled account.

9. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. A GET request with a URL returns a PNG, JPEG, WebP, or PDF. Cookie banners, newsletter popups, and chat widgets from more than 60 known consent platforms are removed before capture; each cleanup step can be disabled. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies page verdict and billing status in headers.

It also offers an MCP server for Claude, Cursor, and other MCP clients, with take_screenshot, get_page_info, and capture_pdf tools. Plans include 1,000 shots per month free with no card; paid plans start at $5 for 3,000. Every feature is available on every plan. See the ScreenshotNeo API documentation.

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

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}`);

Put the API call in your scheduler’s job just as you would any HTTP request, and store the returned bytes. For a recurring production job, keep the key in a secret store and add your scheduler’s timeout, retry, and overlap policy. Sign up for 1,000 free screenshots a month with no card.

10. FAQ

Can I run a scheduled screenshot without keeping a server online?

Potentially, if your existing CI or managed job platform supports scheduled runs and can invoke the API or Selenium worker. Confirm that platform’s runtime, networking, secret, and timeout limits.

Does Selenium Grid schedule captures?

No. Grid routes WebDriver commands to remote browser instances; the recurring trigger remains a separate scheduler.

Should the job capture PDFs instead of screenshots?

Use a PDF when the deliverable is a printable document or needs pagination. Use an image when you need a visual snapshot at a viewport or page region. Both hosted API capture options and Selenium-based workflows should be validated against the intended output.

How do I choose a cadence?

Base it on how often the page changes and how quickly someone must notice. Include the expected number of URLs, retry allowance, and output retention in the operational plan.

Sources