ScreenshotNeo

BlogHow-to

How to Schedule Daily Website Screenshots in CaptureKit

Schedule CaptureKit screenshots with a daily Python job or workflow automation, then save each dated result and handle failures, alerts, and recurring API costs.

By the ScreenshotNeo team4 October 20269 min read

CaptureKit handles the screenshot capture; a separate scheduler triggers its API once a day. You can use a continuously running Python process or a workflow automation service such as Zapier, Make, or n8n. Each run should save the result with a date in its filename or object key so it does not overwrite yesterday’s screenshot.

This guide uses CaptureKit’s documented GET /v1/capture API and x-api-key authentication. Keep the key in a protected environment variable, never in browser-side JavaScript or a public repository. Check the CaptureKit introduction and capture API reference for the current endpoint and fields.

1. Choose where the daily schedule will run

The schedule and the screenshot request are separate jobs. The capture endpoint does not itself create a daily recurrence.

Route Good fit What you operate
Python process You can host a small service or scheduled process and want the schedule in code. A host that stays available, process supervision, logs, and recovery after restarts.
Workflow automation You want a recurring trigger connected to storage or notifications through a visual workflow. The workflow configuration, service connections, and the automation provider’s limits and costs.

CaptureKit’s monitoring guide names Zapier, Make, and n8n as workflow alternatives. The material reviewed does not compare their reliability, pricing, or setup complexity, so compare them against your hosting responsibility, connections, file destination, alert destination, and expected run volume. See CaptureKit’s page-change monitoring guide.

2. Get an API key and choose capture settings

  1. Create a CaptureKit account and obtain an API key from its dashboard.
  2. Store the key as a secret in your host or workflow platform, for example in the CAPTUREKIT_API_KEY environment variable.
  3. Choose the target URL and output format. The API reference lists PNG, JPEG/JPG, WebP, and PDF.
  4. Set the viewport or device emulation and wait behavior to fit the page. Supported wait_until values include domcontentloaded, load, networkidle0, and networkidle2; a delay from 0 to 10 seconds is also documented.
  5. Decide where to retain captures and how to notify someone if a run fails or a visual change needs attention.

These capture options change how a single request renders a page; they do not set the daily schedule. The documented cache_ttl range is 3,600 to 2,592,000 seconds. It controls response caching, not recurrence. For daily archives, ensure the cache behavior suits your need for a fresh capture.

3. Schedule the API call with Python

The following runnable example uses the schedule and requests packages. It captures one page per day, saves the response under a date-stamped name, logs errors, and continues running after a failed request. Install dependencies with python -m pip install requests schedule, set the API key and page URL, then run the script on a host that remains available.

import logging
import os
import time
from datetime import date
from pathlib import Path

import requests
import schedule

API_KEY = os.environ["CAPTUREKIT_API_KEY"]
PAGE_URL = os.environ.get("PAGE_URL", "https://example.com")
OUTPUT_DIR = Path(os.environ.get("OUTPUT_DIR", "captures"))

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")


def capture_daily():
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    day = date.today().isoformat()
    output_path = OUTPUT_DIR / f"page-{day}.png"

    try:
        response = requests.get(
            "https://api.capturekit.dev/v1/capture",
            headers={"x-api-key": API_KEY},
            params={
                "url": PAGE_URL,
                "format": "png",
                "wait_until": "networkidle2",
                "delay": 2,
            },
            timeout=120,
        )
        response.raise_for_status()
        output_path.write_bytes(response.content)
        logging.info("Saved screenshot to %s", output_path)
    except requests.RequestException:
        logging.exception("Screenshot request failed for %s", PAGE_URL)


schedule.every().day.at("08:00").do(capture_daily)
logging.info("Daily capture scheduled; process must stay running")

while True:
    schedule.run_pending()
    time.sleep(30)

Replace https://example.com with the page you own or are authorized to capture. The example schedules the run at 08:00 according to the host’s local clock. Set the host timezone deliberately, or adapt the scheduler to your deployment’s timezone requirements. It does not run a missed job immediately after downtime; use a persistent scheduler or add a last-success check if missed captures must be recovered.

Run it under a process manager

A loop is simple, but the host must keep it alive. Run it as a managed service or container with restart-on-failure, send logs to a place you monitor, and check that the process is active. For a one-shot scheduled task, move the capture function into a script invoked by the host’s daily scheduler. That avoids a permanently running loop, while the host scheduler becomes responsible for recurrence and missed-run behavior.

4. Schedule it in Zapier, Make, or n8n

  1. Create a daily or recurring trigger at the required time and timezone.
  2. Add an HTTP request step that calls CaptureKit’s /v1/capture endpoint with the target URL and selected capture options.
  3. Provide the API key as the x-api-key header using the platform’s secret or credential facility.
  4. Route the response to storage. Use a date or timestamp in the filename or object key so each run is retained separately.
  5. Add a failure path that records the error and sends an email or Slack notification if appropriate.
  6. If you are monitoring changes, compare the new image with the previous capture and notify only when the difference merits review.

CaptureKit documents S3-compatible upload parameters in its API reference. Its monitoring guide describes Google Drive or S3 storage and Slack or email notifications. Exact automation steps depend on the provider and its current integrations; follow its current documentation for credential handling and workflow limits.

5. Save results and avoid overwriting history

Use a date-stamped filename such as page-2026-10-04.png, or a date-based object key such as screenshots/page/2026/10/04.png. If you need more than one capture per day, include the scheduled time or a run identifier. Decide how long to retain the files and who can access them. For an archive, verify that the storage step succeeded before treating the run as complete.

For visual monitoring, compare the latest file with the previous successful capture rather than with the previous calendar day: a failed or skipped run should not become the baseline. Choose a difference threshold that filters harmless rendering variation for your page, and send a review link or image with the alert where your workflow supports it.

6. Cost, performance, and reliability

  • Budget: CaptureKit documents one credit per screenshot capture call. At one page per day, that is about 30 calls per 30-day month; multiply by the number of pages and any extra retries or formats requested as separate calls. Check current account limits and billing before increasing volume.
  • Successful versus failed requests: CaptureKit’s introduction says synchronous calls are billed on a successful HTTP 200 response. For asynchronous requests, HTTP 202 means the job was accepted and queued; billing occurs when it completes successfully, polling is free, and failed jobs are not billed according to that documentation. Confirm current billing terms in the docs.
  • Render time: Wait conditions and fixed delays can make capture slower. Use the least waiting that reliably includes the content you need. A page with late-loading images or client-rendered content may need a selector wait or a different readiness condition if supported by the endpoint options.
  • Retries: Retry transient network errors and server failures with a small bounded backoff. Avoid rapid unlimited retries, which can create duplicate work or exceed a workflow’s limits. Do not retry authentication or invalid-parameter errors unchanged.
  • Daily continuity: A Python loop stops if its host or process stops. Use a service manager, monitoring, and a recovery policy. A managed automation trigger has its own execution history and operational limits; check those before relying on it for an archive.
  • Freshness: Caching is separate from scheduling. Set or omit cache_ttl with the intended freshness in mind, and do not assume that a daily trigger guarantees a newly rendered page.

7. Troubleshooting

Symptom Likely cause What to check or change
401 or 403 response Missing, invalid, or improperly supplied API key. Check the key in the secret store and confirm it is sent in the x-api-key header.
400 response Invalid URL or unsupported option/value. Check the endpoint reference for parameter names, accepted format, viewport, wait mode, and ranges.
Timeout or incomplete page The page takes longer to load, waits for persistent network activity, or renders content after initial load. Choose an appropriate wait_until, use a supported delay within 0–10 seconds, and keep the client timeout long enough for capture completion.
File exists but is not a usable image The response body may be an error payload or another format despite the expected filename. Check the HTTP status before writing bytes, inspect response headers and content type, and match the extension to the requested output.
Every day’s file replaces the last The storage path is static. Include the date, time, or run identifier in the filename or object key.
No capture after the scheduled time The Python process was stopped, the host timezone differs, or the automation trigger did not execute. Inspect process and workflow history, verify the timezone, and decide how to catch up after downtime.
Unexpectedly stale screenshot Response caching or a target page cache may return old content. Review cache_ttl and the page’s own caching behavior; caching duration is not the daily schedule interval.
Repeated or duplicate captures Both the app and host scheduler trigger the job, or retries repeat a successful operation. Use one recurrence source, log a run ID, and make storage writes idempotent where possible.

8. A pre-launch checklist

  • The API key is stored as a secret and does not appear in source control or client-side code.
  • The schedule time and timezone are explicit.
  • The output format and wait behavior match the target page.
  • Each run writes a unique dated file or object.
  • Failures are logged and visible to someone responsible.
  • Retries are bounded and successful captures are not needlessly repeated.
  • Retention, access, and monthly capture volume are understood.

9. Or skip the browser setup

If you want the screenshot request without managing a browser or capture worker, ScreenshotNeo provides a website screenshot API and MCP server. You still trigger this request from your daily scheduler; the one-call API replaces the capture 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)
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}`);

ScreenshotNeo removes cookie and consent banners, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, and failed loads are never billed, and the response identifies the page verdict and billing status. Its MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

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

10. FAQ

Does CaptureKit run a daily schedule by itself?

No. The capture API takes a screenshot when called; a script or automation workflow supplies the recurring trigger.

Does cache_ttl mean “capture every day”?

No. It controls caching for a response. Configure recurrence separately in your scheduler.

Can the Python example catch up after the host was offline?

Not by itself. The in-memory schedule waits for the next scheduled time after the process starts. Add persistent run tracking and catch-up logic, or use a scheduler with the recovery behavior you need.

How do I know whether the page changed?

Retain each successful capture, compare it with the last successful image, and alert on meaningful differences. Set the comparison behavior for the page’s normal visual variation.