ScreenshotNeo

BlogHow-to

How to Save CaptureKit Screenshots Directly to Amazon S3

CaptureKit advertises S3 uploads, but its public docs do not confirm custom-bucket settings. Here’s what to verify and how to upload screenshot bytes safely.

By the ScreenshotNeo team4 October 202610 min read

Short answer: CaptureKit’s product page advertises “S3 uploads included,” but the public documentation reviewed for this guide does not establish the endpoint parameter, credentials, or whether the destination can be a bucket you own. Do not guess those settings. Confirm them in the current CaptureKit documentation or with CaptureKit support. If your CaptureKit workflow returns screenshot bytes to your backend, you can upload those bytes to Amazon S3 with an AWS SDK or REST API.

CaptureKit advertises screenshot and PDF output in PNG, WebP, JPEG, or PDF formats. That is a vendor feature statement, not independent verification of a customer-controlled S3 upload configuration. CaptureKit product page

What “directly to S3” can mean

There are two possible workflows, and they require different setup:

  1. Managed upload: CaptureKit captures the page and uploads the result to S3. Its product page advertises S3 uploads, but the reviewed material does not clarify how to select a customer-owned bucket or configure that destination.
  2. Backend upload: Your backend requests a screenshot, receives the response bytes, and writes them to S3 using AWS SDK, CLI, or REST operations. This works only if the CaptureKit endpoint and plan you use return the image data to your caller.

CaptureKit’s general help material describes API-key use and calling endpoints from a backend, but does not document the screenshot-to-custom-bucket parameters. Verify the current endpoint behavior before implementing either path.

Confirm the integration details first

Before writing production code, get answers to these specific questions from the current CaptureKit endpoint reference or support:

  • Which screenshot endpoint and authentication method should your backend use?
  • Does the endpoint return image bytes, a temporary download URL, or only an upload result?
  • For managed S3 uploads, can you select a bucket you own? Which Region, bucket name, and credentials or role are required?
  • What request option enables the upload, and how are upload errors reported?
  • Which output formats are accepted for the upload path?
  • If the backend receives bytes, what response status and headers identify the file format and successful capture?

Do not copy guessed parameter names or credentials into an integration. Keep CaptureKit API keys and AWS credentials on the server, in backend configuration or a secret store; do not expose them in browser JavaScript.

Plan the S3 object layout

Amazon S3 stores files as objects inside buckets. An object consists of file data and metadata. Before enabling uploads, decide how your objects should be named and retained. AWS: Getting started with Amazon S3

  • Bucket and Region: select the destination and confirm that your upload identity can write there.
  • Object key: choose a filename and optional prefix, such as captures/example.com/2026-10-04/page.webp. Prefixes help group captures by site, date, or workflow.
  • Overwrite behavior: a stable key replaces the current object at that key. In a versioning-enabled bucket, an upload to an existing key creates another version. Pick stable or unique keys intentionally.
  • Metadata: decide whether the object needs a content type or user-defined metadata. AWS says user-defined metadata is set at upload time; changing it later requires copying the object.
  • Permissions: the identity that performs the upload needs write permission for the bucket. Grant only the access needed for the destination and key layout. AWS: Uploading objects

Backend upload pattern when you receive screenshot bytes

The following is a complete S3 upload example once your verified CaptureKit integration has provided screenshot bytes. The CaptureKit request is deliberately represented as an integration boundary because the reviewed public documentation does not establish its exact screenshot endpoint request shape or a custom-bucket option. Replace that function with the documented CaptureKit call and ensure it returns the raw image bytes before using the S3 upload code.

Python with boto3

import os
from datetime import date
from urllib.parse import urlparse

import boto3


def capturekit_screenshot_bytes(page_url: str) -> tuple[bytes, str]:
    """Implement using CaptureKit's currently documented screenshot endpoint.

    Return (raw_image_bytes, content_type), for example
    (b"...", "image/png"). Do not assume an endpoint parameter name;
    verify it in CaptureKit's current API reference.
    """
    raise NotImplementedError("Add the verified CaptureKit API request")


def save_screenshot(page_url: str) -> str:
    image_bytes, content_type = capturekit_screenshot_bytes(page_url)
    parsed = urlparse(page_url)
    host = parsed.hostname or "unknown-host"
    key = f"captures/{host}/{date.today().isoformat()}/page.png"

    s3 = boto3.client("s3", region_name=os.environ["AWS_REGION"])
    s3.put_object(
        Bucket=os.environ["S3_BUCKET"],
        Key=key,
        Body=image_bytes,
        ContentType=content_type,
    )
    return key


if __name__ == "__main__":
    print(save_screenshot("https://example.com"))

Install the SDK with python -m pip install boto3. Configure AWS credentials using the AWS SDK’s standard credential provider chain, and set AWS_REGION and S3_BUCKET in the backend environment. The example uses the current date in the key; choose a collision-resistant naming scheme if multiple captures can occur for the same host and date.

Node.js with AWS SDK for JavaScript v3

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

async function capturekitScreenshotBytes(pageUrl) {
  // Implement using CaptureKit's currently documented screenshot endpoint.
  // Return { bytes: Buffer, contentType: "image/png" }.
  // Verify its endpoint and request options in the current API reference.
  throw new Error("Add the verified CaptureKit API request");
}

const s3 = new S3Client({ region: process.env.AWS_REGION });

async function saveScreenshot(pageUrl) {
  const { bytes, contentType } = await capturekitScreenshotBytes(pageUrl);
  const host = new URL(pageUrl).hostname;
  const key = `captures/${host}/${new Date().toISOString().slice(0, 10)}/page.png`;

  await s3.send(new PutObjectCommand({
    Bucket: process.env.S3_BUCKET,
    Key: key,
    Body: bytes,
    ContentType: contentType,
  }));
  return key;
}

console.log(await saveScreenshot("https://example.com"));

Install the package with npm install @aws-sdk/client-s3. Provide AWS credentials through the SDK’s standard provider chain and set AWS_REGION and S3_BUCKET. As with Python, the CaptureKit function must be filled in from its verified API documentation.

cURL for uploading an image file already saved by your workflow

If your verified CaptureKit workflow saves the screenshot to a local file, the AWS CLI can upload it. The CLI uses the configured AWS credentials and region:

aws s3 cp ./capture.png s3://YOUR_BUCKET/captures/example.com/capture.png \
  --content-type image/png

This command uploads an existing file; it does not make a CaptureKit screenshot request. For a direct REST upload, follow AWS’s documented signing and authorization requirements rather than placing long-lived AWS keys in a URL.

Choose managed uploads or backend uploads

Pattern When it fits What to verify
CaptureKit-managed S3 upload You want the capture service to handle storage as part of the capture workflow. Whether the destination can be your bucket, required configuration and credentials, supported keys and metadata, and how failures are returned.
Backend receives bytes, then uploads Your application needs to choose keys, set metadata, or control the S3 operation. That the CaptureKit endpoint returns image bytes or a retrievable result and that your backend can read it reliably.

The first option is advertised by CaptureKit, but the reviewed documentation does not establish custom-bucket configuration. The second is a general AWS pattern, conditional on CaptureKit returning the screenshot result to your backend.

Object keys, versions, and metadata

Stable keys versus unique keys

A stable key such as captures/example.com/latest.png is convenient when consumers need one current image. Repeated uploads target the same key. A date or unique identifier in the key preserves multiple captures and makes concurrent writes less likely to collide. In a versioning-enabled bucket, even stable-key uploads create new object versions; lifecycle and retention decisions should account for that behavior. AWS: Uploading objects

Content type and custom metadata

Set a matching content type at upload time, for example image/png, image/jpeg, or image/webp, based on the actual response. Do not infer the type solely from a requested format if the service can return an error document or another response. User-defined metadata must be supplied during upload; updating it later requires copying the object. AWS: Working with object metadata

Reliability, performance, and cost considerations

  • Bounded timeouts: screenshot capture may take longer than an ordinary API request. Set a timeout based on the verified CaptureKit endpoint behavior, and avoid retrying a request without understanding whether it can create duplicate captures or uploads.
  • Retry uploads separately: if the capture succeeded but S3 failed, retain or reacquire the bytes and retry the S3 operation. Use a deliberate key strategy so retries do not create accidental duplicates or unwanted versions.
  • Keep memory use bounded: for a service handling large screenshots or concurrent jobs, stream data when the SDK and capture response permit it instead of buffering many full images in memory.
  • Check both stages: record capture status and S3 upload status separately. A successful screenshot request does not prove that the object was written, and an upload error should not be reported as a capture failure without distinction.
  • Budget the storage workflow: account for screenshot generation, S3 storage, and any requests to retrieve the objects. The supplied source material establishes no pricing or performance figures for this combined workflow, so estimate from your actual formats, capture volume, retention, and AWS pricing.
  • Limit access: keep API keys and AWS credentials in backend configuration or a secret store. Give the upload identity only the bucket write access required by the integration.

Troubleshooting

Symptom Likely cause What to check
CaptureKit call returns an authorization error Missing, invalid, or incorrectly supplied API key. Use the authentication method in the current CaptureKit API reference; keep the key on the backend and check that the request reaches the expected endpoint.
You cannot find a documented custom-bucket parameter The reviewed general help page does not specify one. Check the current screenshot endpoint reference or ask CaptureKit support. Do not guess an option name or assume the advertised S3 feature targets your bucket.
S3 returns AccessDenied The active AWS identity lacks write permission for the destination, or the destination configuration is wrong. Confirm the identity, bucket, Region, and required write permissions with your AWS administrator. AWS documents that write permission is needed to upload.
Object exists but browsers handle it incorrectly The content type may be missing or inconsistent with the bytes. Set the correct content type when uploading and confirm that the CaptureKit response is an image rather than an error payload.
Repeated jobs overwrite a previous capture They use the same object key. Use a unique or date-based prefix if each capture should be retained; decide how S3 versioning should behave.
Unexpected extra versions accumulate Versioning is enabled and uploads reuse a key. Choose unique keys or set an appropriate retention policy for versions.
Metadata changes do not appear after upload User-defined metadata is set during upload. Send the desired metadata with the original upload. AWS notes that changing it later requires copying the object.
Backend times out or memory rises under load Captures or responses are large, requests are concurrent, or timeouts are too short. Use bounded concurrency, an appropriate timeout, and streaming where supported. Separate capture and upload timing in logs.

Or skip the browser setup

For a screenshot API with a documented one-call image response, ScreenshotNeo can return a screenshot you can then upload to S3 from your backend. Its API supports PNG, JPEG, and WebP output; use the documented format option when you need a particular one. ScreenshotNeo does not claim in the facts provided here to write directly to your S3 bucket, so the S3 upload remains your backend’s step. See the ScreenshotNeo API documentation.

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,
)
r.raise_for_status()
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = Buffer.from(await res.arrayBuffer());

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot. Bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Save the returned bytes to S3 with the AWS SDK pattern above. Sign up for 1,000 free screenshots a month, no card required.

FAQ

Does CaptureKit definitely upload to my own S3 bucket?

Its product page advertises S3 uploads, but the public material reviewed here does not confirm customer-owned bucket configuration. Verify the current endpoint reference or ask CaptureKit support.

Can I use a public bucket?

The upload examples do not require a public bucket. Decide separately how applications or users should access stored objects, following your organization’s access policy.

Should I store a screenshot URL or the image bytes?

Use the option supported by the verified CaptureKit response and your retention needs. If the endpoint returns bytes, uploading those bytes gives your backend direct control over the S3 key and upload metadata.

Can I add metadata after the object is uploaded?

AWS says user-defined metadata is set during upload; changing it later requires copying the object. Include required metadata in the initial write.