ScreenshotNeo

BlogHow-to

How to Automate ScreenshotAPI.net Captures with Cron

Run ScreenshotAPI.net captures on a cron schedule with a secure Python script, reliable file handling, and clear troubleshooting steps.

By the ScreenshotNeo team4 October 20267 min read

To automate ScreenshotAPI.net captures with cron, write a script that makes one screenshot request and exits, then schedule that script on a server that stays available. Cron controls when the script runs; the script handles authentication, the target URL, and saving each response.

ScreenshotAPI.net also offers a managed recurring scheduler in its dashboard. Choose self-hosted cron when you want to own the script and output handling. Choose its managed scheduler when you want to configure recurring captures through the service and review stored screenshots there.

1. Create a one-shot Python capture script

The documented endpoint is GET https://shot.screenshotapi.net/v3/screenshot. The request takes a token API key and a url to render. Keep the token in server-side configuration, not browser code or a public repository. See the vendor’s render documentation for the endpoint and supported rendering parameters.

Install the dependency:

python3 -m pip install requests

Save this as capture.py. It uses a UTC timestamp in the output name to avoid replacing earlier captures:

#!/usr/bin/env python3
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

import requests

ENDPOINT = "https://shot.screenshotapi.net/v3/screenshot"
TARGET_URL = os.environ.get("CAPTURE_URL", "https://example.com")
OUTPUT_DIR = Path(os.environ.get("CAPTURE_DIR", "/var/lib/site-captures"))


def main():
    token = os.environ.get("SCREENSHOTAPI_TOKEN")
    if not token:
        print("SCREENSHOTAPI_TOKEN is not set", file=sys.stderr)
        return 2

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

    try:
        response = requests.get(
            ENDPOINT,
            params={"token": token, "url": TARGET_URL},
            timeout=(10, 120),
        )
        response.raise_for_status()
        if not response.content:
            raise RuntimeError("The API returned an empty response")
        destination.write_bytes(response.content)
        print(f"Saved {destination}")
        return 0
    except (requests.RequestException, OSError, RuntimeError) as exc:
        print(f"Capture failed: {exc}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())

Set SCREENSHOTAPI_TOKEN and optionally CAPTURE_URL and CAPTURE_DIR in the process environment. Use a URL you control for the initial check. The example saves the response bytes with a PNG extension; if you request another output format, use a matching extension and confirm the format parameter against the vendor’s current render docs.

Run it once before scheduling

Use the same Unix account that will own the cron job, with the environment set and destination directory writable. Confirm that the request succeeds, the file is created, and successive runs create distinct files. This catches authentication, network, URL encoding, and filesystem permission issues before cron obscures the context.

2. Add a cron schedule

Open the crontab for the account that should run the capture:

crontab -e

For a daily run at 08:00 according to the server’s cron timezone, the vendor tutorial’s example is:

0 8 * * * /usr/bin/python3 /opt/site-capture/capture.py >> /var/log/site-capture.log 2>&1

Use the actual absolute paths on your host. Cron often has a smaller environment than an interactive shell, so define required variables in the crontab or load them from a protected configuration file. For example:

SCREENSHOTAPI_TOKEN=replace_with_secret
CAPTURE_URL=https://example.com
CAPTURE_DIR=/var/lib/site-captures
0 8 * * * /usr/bin/python3 /opt/site-capture/capture.py >> /var/log/site-capture.log 2>&1

Restrict access to the crontab and log files because they may contain operational details. Avoid putting a real token in a shared crontab, script, or source repository; use your host’s protected secret mechanism where available.

Cron expression reference

Expression Schedule
0 8 * * * Daily at 08:00
0 * * * * At the start of every hour
*/15 * * * * Every 15 minutes
0 8 * * 1-5 Weekdays at 08:00
0 0 * * 0 Weekly on Sunday at midnight on many cron implementations

Traditional cron entries have five time fields: minute, hour, day of month, month, and day of week. Check the cron implementation and host timezone when day-of-week numbering or daylight-saving behavior matters. The ScreenshotAPI.net sources reviewed for this guide do not establish timezone semantics for its managed scheduler.

3. Choose self-hosted cron or managed scheduling

Consideration Self-hosted cron ScreenshotAPI.net managed scheduler
Where it runs Your server; it must be available at the scheduled time. The service runs the recurring capture.
Operations You maintain the host, script, logs, and destination storage. Configure and manage jobs in the dashboard.
Results Your script saves or forwards the API response. The service stores managed captures for later review.
Control Easy to integrate with your own processing and storage. Less server and script maintenance for recurring captures.

The managed setup uses Query Builder: enter the URL and capture settings, choose scheduled screenshot, and set a preset or custom schedule. Manage jobs under Schedule Requests. The documentation describes hourly, daily, weekly, and custom schedules. Starting and stopping control future execution; deleting a job permanently removes the screenshots associated with it. Download anything you need to preserve before deletion. See Schedule Capture Jobs and the Query Builder documentation.

4. cURL, Python, and Node.js request examples

The cron example above uses Python, but any script or executable that makes one request and exits can be scheduled. These examples show the documented GET request. Store the token in an environment variable before running them.

cURL

curl --fail --get 'https://shot.screenshotapi.net/v3/screenshot' \
  --data-urlencode "token=$SCREENSHOTAPI_TOKEN" \
  --data-urlencode 'url=https://example.com' \
  --output capture.png

Python

import os
from pathlib import Path
import requests

response = requests.get(
    "https://shot.screenshotapi.net/v3/screenshot",
    params={"token": os.environ["SCREENSHOTAPI_TOKEN"], "url": "https://example.com"},
    timeout=(10, 120),
)
response.raise_for_status()
Path("capture.png").write_bytes(response.content)

Node.js

const endpoint = new URL('https://shot.screenshotapi.net/v3/screenshot');
endpoint.searchParams.set('token', process.env.SCREENSHOTAPI_TOKEN);
endpoint.searchParams.set('url', 'https://example.com');

const response = await fetch(endpoint, { signal: AbortSignal.timeout(120000) });
if (!response.ok) {
  throw new Error(`Screenshot request failed: HTTP ${response.status}`);
}
const bytes = new Uint8Array(await response.arrayBuffer());
await (await import('node:fs/promises')).writeFile('capture.png', bytes);

These minimal examples rely on the API’s documented request shape. Add optional rendering parameters only when needed, using their documented names and values. URL-encode query values; the libraries above do that for you.

5. Reliability, performance, and cost considerations

  • Use a host that stays up. A local laptop that sleeps or disconnects cannot run its scheduled cron process. A server or managed scheduler avoids depending on your workstation being present.
  • Keep output unique. Timestamped filenames prevent routine overwrites. The vendor’s render documentation warns that reusing a non-unique result filename can overwrite an earlier result.
  • Set a timeout and log failures. A bounded request timeout lets the process exit instead of hanging indefinitely. Keep standard output and errors, and monitor the log or exit status using your existing operations tooling.
  • Use a sensible cadence. Frequent captures multiply request volume and stored files. Match the schedule to how quickly the page changes and the account’s current limits.
  • Account for page rendering. Dynamic pages may need documented wait or delay options. Increasing frequency does not fix a capture that occurs before content renders.
  • Plan for retries carefully. The reviewed sources do not document cron-side retry behavior or API retry guarantees. If you implement retries, cap attempts and avoid overlapping runs; confirm current vendor guidance for any request limits.
  • Check current account details. The reviewed sources do not establish current plan quotas, pricing, managed scheduler timezone, retry behavior, or failure alerts. Verify these in the account dashboard or with official support if they affect your design.

6. Troubleshooting

Symptom Likely cause What to check
Works in terminal, fails from cron Cron has a different PATH, working directory, or environment. Use absolute interpreter/script paths; set variables explicitly; inspect redirected logs.
Authentication error Missing, misspelled, or invalid token. Check that SCREENSHOTAPI_TOKEN is available to the cron process and that the request uses the documented token parameter.
Bad request or wrong page Malformed or unencoded URL, or missing required query value. Pass parameters through a query encoder such as Python Requests or URLSearchParams, and verify the target URL.
No file is saved Output directory does not exist or the cron account lacks permission. Create the directory and grant the job account write access; inspect the process exit code and log.
Old image is replaced Each run uses the same output filename. Include a timestamp or another unique run identifier in the filename.
Capture is blank or incomplete Page content may load asynchronously or require a rendering wait. Review the API’s documented wait and delay parameters and test them manually before scheduling.
Runs overlap or consume too many requests Schedule interval is shorter than request duration or unnecessarily frequent. Choose a cadence based on page change rate and prevent a second process from starting while the first is active.
Managed screenshots disappear The scheduled job was deleted rather than stopped. Stopping pauses the job; deletion permanently removes the associated screenshots. Preserve required files before deleting.

Or skip the browser setup

ScreenshotNeo offers a one-call screenshot API and an MCP server for AI agents. Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, timeouts, and failed loads are never billed; responses identify the page verdict and billing status. It can also capture PDFs, full pages, or selected elements, and offers caching and bulk capture.

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com \
  -o shot.webp

See the ScreenshotNeo API docs for the request options. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.

FAQ

Do I need to keep my computer on for scheduled screenshots?

For self-hosted cron, the host running cron must be available at the scheduled time. Your personal computer does not need to stay on if the job runs on an always-on server. The managed scheduler runs through ScreenshotAPI.net.

Can cron run every few minutes?

Yes. For example, */15 * * * * requests a run every 15 minutes on standard cron implementations. Consider request volume, page change frequency, execution time, and account limits before choosing a short interval.

How is cron different from ScreenshotAPI.net’s Schedule Website Screenshot feature?

Cron runs your script on a host you operate, so you manage execution and output storage. The managed feature is configured in the vendor dashboard and stores the recurring screenshots for review.

Does stopping a managed job delete its screenshot history?

The documentation says stopping pauses future runs without deleting the job. Deleting the job permanently removes its related screenshots.