ScreenshotNeo

BlogComparisons

CaptureKit API vs ScreenshotOne for Bulk Website Screenshots

Compare bulk submission, capture controls, rate limits, billing, and queue design for CaptureKit and ScreenshotOne, with code and a cost checklist.

By the ScreenshotNeo team4 October 202613 min read

For a documented, single-call batch submission, ScreenshotOne has a dedicated POST /bulk endpoint that accepts a list of screenshot requests. It is lazy by default: the captures run when you download the returned screenshot URLs. Set execute: true to request execution before the bulk call returns, and allow time for the captures to finish. CaptureKit documents a per-capture endpoint and a range of capture controls, but the documentation reviewed here does not establish whether it has a separate bulk endpoint. Check its current API reference before deciding whether to submit a batch or run your own queue.

For a third option to evaluate first, ScreenshotNeo offers bulk capture for up to 100 URLs per call, and bills only clean shots. Its API and MCP server are intended for developers automating website captures.

1. What matters when capturing many URLs

Bulk screenshots are a queueing and accounting problem as much as an API choice. Decide how you will submit work, pace requests, handle partial failures, and account for repeated captures and cache misses. Compare the providers using the same URL list, capture settings, frequency, and success assumptions.

Need What to check
Batch submission Whether one request accepts many capture jobs, and how each result is returned.
Execution timing Whether jobs start immediately, only when result URLs are fetched, or after an explicit execution option.
Throughput Requests started per minute, queue limits, reset behavior, and whether limits apply across the workspace.
Capture requirements Formats, full-page behavior, device and viewport settings, selector capture, and any scroll-to-load option.
Usage accounting What counts as a billable capture, how cache hits and misses work, and whether failures or retries use quota.
Operations How you persist jobs, retry transient errors, avoid duplicates, and resume after a worker restart.

2. The short comparison

Service Bulk approach Useful documented details Best fit to evaluate
ScreenshotNeo Bulk capture up to 100 URLs per call. Cookie and consent banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Has an MCP server for AI agents. Teams that want bulk captures, cleaner page images, and billing that identifies clean shots.
ScreenshotOne Documented POST /bulk wrapper accepts a list. Lazy by default; execute: true requests execution in advance. Shared options can apply across requests and be overridden per item. Usage endpoint reports the remaining request-start allowance and reset time for a one-minute bucket. Teams that need a documented batch wrapper and can build a queue around its execution and rate-limit semantics.
CaptureKit The reviewed reference documents an individual GET /v1/capture endpoint. Its separate bulk endpoint status is not established by the sources reviewed. Documents PNG, JPEG/JPG, WebP, and PDF; full-page capture, optional scrolling, device emulation, viewport controls, cache, and selector capture. One credit per capture call. Teams whose required capture controls or credit plan fit, after checking its current API reference for batch behavior and limits.

The available documentation does not provide an independent head-to-head speed, fidelity, or uptime comparison. Choose based on documented workflow and your own representative capture requirements; do not infer equivalent performance from plan sizes.

3. ScreenshotOne bulk workflow

ScreenshotOne documents a bulk wrapper at POST https://api.screenshotone.com/bulk. Its bulk documentation describes a requests list of screenshot requests. Shared options can be set once and overridden for an individual request. With default lazy behavior, the response provides screenshot URLs and work is deferred until those URLs are downloaded. If you set execute: true, the service executes requests before returning; the documentation advises allowing enough time for all captures to complete.

The API reference and examples are authoritative for the exact option schema and response shape: ScreenshotOne Bulk Screenshots documentation. The sample below illustrates the documented request shape and lazy flow. Confirm accepted fields and response parsing against the current documentation before using it in production.

Example bulk request

curl -X POST "https://api.screenshotone.com/bulk" \
  -H "Content-Type: application/json" \
  -d '{
    "access_key": "YOUR_ACCESS_KEY",
    "requests": [
      {"url": "https://example.com"},
      {"url": "https://example.org"}
    ]
  }'

For a production batch, include only options supported by the provider and required by your workload. Put common settings at the shared level when the bulk schema supports them, then override per item only where needed. Treat the returned result as a set of jobs or screenshot URLs, not as proof that every image is already rendered under the default lazy behavior.

Execution choices

  • Lazy (default): store each returned screenshot URL and download it when your downstream process is ready. Account for rendering at download time.
  • Execute in advance: set execute: true when you want the bulk submission to trigger captures before downloading. Allow sufficient completion time, and handle a delayed or incomplete set of results.
  • Your own worker queue: use when the input set is too large for one operational unit, you need durable retries, or you want to control pacing and progress reporting. Submit manageable chunks and persist each URL and result status.

Using the usage endpoint to pace work

Do not read ScreenshotOne’s concurrency.limit, remaining, or reset as a count of simultaneous active browser renders. They describe the number of screenshot requests that may be started in the current one-minute bucket. Read the usage endpoint, pace new submissions according to remaining allowance, and respect the reset time. ScreenshotOne explicitly says bulk requests consume the same one-minute request bucket as regular screenshot requests. See Get Usage documentation.

For durable work, persist pending jobs outside the worker process. ScreenshotOne’s usage guide suggests a proper queue such as Redis/BullMQ or SQS. Store enough state to resume after a restart, and make result handling idempotent so a retry does not create duplicate downstream records.

4. CaptureKit API workflow

CaptureKit’s documented capture interface is GET /v1/capture, with the API key sent in the x-api-key header. The official capture reference describes one credit per capture call and options including output formats, full-page capture, optional scroll-to-load behavior, device emulation, viewport size, cache controls, and CSS selector capture. See CaptureKit Capture documentation and CaptureKit overview.

The sources used for this comparison do not settle whether CaptureKit also offers a dedicated bulk endpoint. If the current reference still only documents individual calls for your use case, put those calls behind your own queue: persist the URL and options, apply workspace rate limits, retry transient failures with backoff, and record each result independently. Do not assume the individual endpoint proves that no batch endpoint exists.

CaptureKit options to compare against your workload

  • Format: PNG, JPEG/JPG, WebP, or PDF, as supported by the capture reference.
  • Page extent: full-page capture when the full document is needed.
  • Lazy content: optional scrolling to trigger content that loads while scrolling.
  • Target: viewport settings or a CSS selector when only one component is needed.
  • Emulation: device emulation if the same page must be captured in different layouts.
  • Cache: decide whether the cache behavior matches how fresh the output must be.

Check the current CaptureKit reference for exact parameter names, allowed values, response format, authentication details, and rate limits before wiring these settings into a batch worker.

5. Runnable client code for ScreenshotOne bulk

The following examples submit two URLs using the documented bulk endpoint and request list. They intentionally keep the payload small; consult the bulk reference linked above for current shared options, per-request overrides, execution mode, and response schema. Save and inspect the response before assuming a particular JSON shape.

cURL

curl -X POST "https://api.screenshotone.com/bulk" \
  -H "Content-Type: application/json" \
  -d '{
    "access_key": "YOUR_ACCESS_KEY",
    "requests": [
      {"url": "https://example.com"},
      {"url": "https://example.org"}
    ]
  }' -o bulk-response.json

Python

import json
import requests

endpoint = "https://api.screenshotone.com/bulk"
payload = {
    "access_key": "YOUR_ACCESS_KEY",
    "requests": [
        {"url": "https://example.com"},
        {"url": "https://example.org"},
    ],
}

response = requests.post(endpoint, json=payload, timeout=90)
response.raise_for_status()
result = response.json()
print(json.dumps(result, indent=2))

Node.js

const endpoint = 'https://api.screenshotone.com/bulk';
const payload = {
  access_key: process.env.SCREENSHOTONE_ACCESS_KEY,
  requests: [
    { url: 'https://example.com' },
    { url: 'https://example.org' },
  ],
};

if (!payload.access_key) {
  throw new Error('Set SCREENSHOTONE_ACCESS_KEY before running this script');
}

const response = await fetch(endpoint, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload),
});

if (!response.ok) {
  throw new Error(`Bulk request failed: HTTP ${response.status} ${await response.text()}`);
}

console.log(JSON.stringify(await response.json(), null, 2));

These snippets submit the batch request; they do not assume the response shape or download deferred screenshots. Use the current API documentation to read the returned URLs, download them, and determine how per-item failures are represented.

6. Queue design for large URL sets

  1. Normalize input. Validate each URL, remove accidental duplicates if the use case allows, and retain a stable identifier for every requested page.
  2. Define a capture key. Include the URL and all output-affecting options, such as viewport, format, selector, and device. This helps distinguish a true duplicate from a different requested variant.
  3. Persist jobs before submission. Track pending, submitted, downloaded, failed, and retry states in durable storage.
  4. Chunk deliberately. A batch is a submission unit, not a guarantee of simultaneous rendering. Choose chunk size based on API limits, response handling, and how much work you are willing to retry.
  5. Pace from provider limits. For ScreenshotOne, use usage values and the reset time for its one-minute start bucket. For CaptureKit, obtain the account’s live limits; its plan quota and rate limits are shared across API keys in a workspace.
  6. Separate transient from permanent errors. Retry timeouts and temporary network or server errors with bounded exponential backoff and jitter. Do not repeatedly retry invalid parameters or inaccessible URLs without changing the cause.
  7. Make downstream writes idempotent. Persist the capture key and provider result so a worker retry cannot publish the same output twice.
  8. Keep a failure ledger. Record the URL, capture options, attempt count, provider response, and next action. This makes partial batches repairable without rerunning the entire input set.

7. Pricing and fair cost comparison

Published plan prices are snapshots, not a guarantee of current checkout terms. Verify live prices, limits, and overage settings before committing. These providers use different units, so credits and screenshot counts should not be treated as interchangeable.

Provider Published monthly plans in the research snapshot Billing detail
CaptureKit Free trial: 100 credits; Starter: 1,000 for $7; Pro: 10,000 for $29; Ultimate: 50,000 for $89. One credit per capture call. API keys in a workspace share quota and rate limits. Checkout displays the live amount before confirmation.
ScreenshotOne Free: 100 screenshots; Basic: 2,000 for $17 at 40 requests/minute; Growth: 10,000 for $79 at 80/minute; Scale: 50,000 for $259 at 150/minute. Successful unique non-cached renders generally count. HTTP, browser, and network failures do not count. Cache misses may rerender and count. Overage depends on account settings and hard limit.
ScreenshotNeo Free: 1,000 shots; Starter: $5 for 3,000; Growth: $15 for 15,000; Pro: $39 for 60,000; Scale: $99 for 250,000; Business: $249 for 1,000,000. Only clean shots are billed. Every feature is on every plan; yearly billing gives two months free.

CaptureKit plan figures are from its plans and pricing documentation; ScreenshotOne figures are from its pricing page snapshot. Recheck those pages before publication or purchase because prices and plan limits can change.

Estimate your real monthly workload

Start with the work you actually expect to bill, not just the number of source URLs:

monthly capture demand = URLs per run
                     × runs per month
                     × capture variants per URL
                     × expected successful unique fraction
                     + expected billable retries

For example, a URL captured as both mobile and desktop is two variants. A weekly schedule is not the same workload as a daily schedule. Estimate cache reuse using the provider’s documented behavior rather than assuming every repeated request is free. For ScreenshotOne, a unique option combination that is not cached counts, and a cache miss may cause a billable rerender. CaptureKit charges one credit per capture call. ScreenshotNeo says cache hits cost nothing and failed loads, blank pages, timeouts, and bot checks are not billed.

Compare at least these inputs before selecting a plan: URLs per run, runs per month, device and viewport variants, output formats, expected cache hit rate, retry rate, how failures are billed, workspace-wide limits, and whether overage is enabled. The least expensive nominal plan may not suit a workload that exceeds its request-start rate.

8. Performance and reliability

No independent benchmark or substantiated uptime comparison is available in the research for these services. Measure your own representative set if response time or fidelity is a selection criterion. Include pages with different load patterns, content sizes, consent banners, client-side rendering, and full-page length; compare like-for-like options and record failures as well as successful captures.

For operational reliability, use durable queues, bounded retries, idempotent result handling, and a way to replay only failed items. Track time from submission to completed download separately from API submission time. For ScreenshotOne’s lazy mode, remember that submission and capture completion are separate events. For its execute mode, leave room for execution and still handle items that do not complete as expected.

9. ScreenshotNeo: bulk screenshots without a browser stack

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It supports bulk capture for up to 100 URLs per call. Before capture, it accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the outcome identified in response headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.

The API can also capture full pages with lazy images loaded, a CSS-selected element, dark mode, device presets or custom viewports, retina output, PDF, HTML/CSS, and more. See the ScreenshotNeo API documentation for the full option set and request details.

One-call capture

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

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 take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.

10. Troubleshooting bulk capture jobs

Symptom Likely cause What to do
Bulk submission succeeds but images are not ready ScreenshotOne’s default bulk mode is lazy; capture runs when returned URLs are downloaded. Download the returned URLs to trigger the work, or use execute: true and allow time for completion.
Requests are throttled despite low apparent concurrency ScreenshotOne’s concurrency values describe request starts in a one-minute bucket, not active renders. Bulk calls share that bucket. Read the usage response, pace starts, and wait until the reported reset when needed.
Many items fail after a worker restart Pending work and result state existed only in process memory. Persist job state before submission and use a durable queue so the worker can resume.
Repeated captures consume more quota than expected Different capture options can form distinct cache entries; cache misses may rerender and count. Retries can add billable calls depending on provider rules. Record the complete option set, estimate unique variants, and review cache and billing rules for each provider.
CaptureKit quota or rate limit is shared unexpectedly CaptureKit states that API keys in one workspace share quota and rate limits. Coordinate workers against workspace-level usage and verify the current account limit.
ScreenshotOne response parser breaks The integration assumes an undocumented or stale response shape. Validate against the current bulk API reference; preserve the raw response for diagnostics.
CaptureKit batch behavior is unclear The reviewed documentation establishes the individual capture endpoint but not the status of a distinct bulk endpoint. Check the current API reference or ask the provider before designing around batch parity.
A full-page result misses content below the fold Some sites load content only after scrolling, or the capture configuration does not trigger that behavior. Use a documented scroll-to-load or lazy-image option where available and validate on pages with long or dynamic content.
Cost estimates do not match invoices Request counts, credits, successful renders, cache misses, retries, and overage settings differ by provider. Reconcile provider usage against per-job logs and verify live plan terms and billing units.

11. Decision guide

  • Try ScreenshotNeo first if you want bulk up to 100 URLs per call, removal of common consent overlays and widgets, explicit page verdict and billing headers, or MCP tools for agents. It includes 1,000 free shots monthly with no card.
  • Choose ScreenshotOne for evaluation when its documented /bulk wrapper and usage endpoint match your queue design. Account for lazy execution and pace against its one-minute request-start bucket.
  • Evaluate CaptureKit when its documented capture controls or credit plan match the workload. Confirm current rate limits and bulk endpoint behavior before you assume how to submit a large list.

For any provider, test the exact required formats and page types, verify current limits and billing terms, and size the queue around starts per minute as well as total monthly capacity.

12. FAQ

Does a ScreenshotOne bulk request render every screenshot immediately?

No. Its documented default is lazy execution, which starts capture when the returned screenshot URL is downloaded. The execute: true option requests execution in advance.

Is ScreenshotOne’s concurrency limit the number of simultaneous browser sessions?

No. The documented values refer to how many screenshot requests can be started in a one-minute bucket.

Does CaptureKit have a bulk endpoint?

The CaptureKit sources reviewed for this comparison do not establish whether it has a separate bulk endpoint. Verify the current API reference before making that assumption.

Can plan prices be compared by dividing dollars by the listed quota?

Only as a rough starting point. CaptureKit credits and ScreenshotOne screenshot requests have different billing rules, and cache, failures, retries, options, and rate limits affect the workload.

Is there a verified speed winner?

No independent head-to-head benchmark was available in the research. Run a controlled comparison on representative pages if latency or output fidelity determines the choice.