ScreenshotNeo

BlogHow-to

How to Capture a Website Screenshot on a Schedule with APITemplate.io

APITemplate.io documents scheduled template image generation, but its current docs do not verify live webpage screenshots. Here is how to schedule a real capture and where APITemplate fits.

By the ScreenshotNeo team4 October 20269 min read

Direct answer: APITemplate.io’s current documentation describes generating images and PDFs from templates and JSON data. The documentation reviewed for this guide does not verify an endpoint that opens an arbitrary live website and captures its rendered page. To schedule an actual website screenshot, you need both a scheduler and a browser-based capture step. You can use APITemplate.io separately when you want to generate a designed image or document from data after the scheduled trigger.

That distinction matters: a scheduled template image is not a screenshot of a live webpage. APITemplate.io’s current first-request guide uses the v2 API, while its older v1 reference says v1 is no longer supported. Use v2 for the documented template-generation workflow. APITemplate.io first API request · legacy API reference notice

1. Separate the schedule, capture, and output

A reliable workflow has three jobs:

  1. Schedule: Cron, a hosted scheduler, or a workflow tool decides when the run starts.
  2. Capture: A browser loads the live page, waits for it to render, and saves an image. APITemplate.io’s documented template API does not establish this live-page capture step.
  3. Store and review: Save each image with a timestamp and stable filename. Decide how long to retain it, which timezone defines the schedule, and what happens when a capture fails.

APITemplate.io documents an n8n workflow using a Cron trigger for recurring report generation. That demonstrates the scheduler-to-template-generation pattern, not webpage screenshot capture. APITemplate.io’s n8n integration guide

2. Capture a live webpage yourself with Playwright and cron

The following Python example runs a headless Chromium browser, visits a URL, waits for the page load event, allows a short settling period, and saves a full-page PNG. It does not call APITemplate.io because the documented API does not verify live-page capture.

Install and save the capture script

python -m venv .venv
. .venv/bin/activate
pip install playwright
playwright install chromium
mkdir -p captures

Save as capture.py:

import asyncio
import os
from datetime import datetime, timezone
from pathlib import Path
from urllib.parse import urlparse

from playwright.async_api import async_playwright

URL = os.environ.get("TARGET_URL", "https://example.com")
OUT_DIR = Path(os.environ.get("CAPTURE_DIR", "captures"))

async def main():
    parsed = urlparse(URL)
    if parsed.scheme not in ("http", "https") or not parsed.netloc:
        raise ValueError("TARGET_URL must be an absolute http:// or https:// URL")

    OUT_DIR.mkdir(parents=True, exist_ok=True)
    stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
    safe_host = parsed.netloc.replace(":", "_")
    output = OUT_DIR / f"{safe_host}-{stamp}.png"

    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page(
            viewport={"width": 1440, "height": 1000},
            device_scale_factor=1,
        )
        response = await page.goto(URL, wait_until="load", timeout=60000)
        if response is None:
            raise RuntimeError("Navigation returned no main-document response")
        if response.status >= 400:
            raise RuntimeError(f"Page returned HTTP {response.status}: {URL}")

        # Adjust for the site: wait for a known selector when possible.
        await page.wait_for_timeout(1500)
        await page.screenshot(path=str(output), full_page=True, animations="disabled")
        await browser.close()

    print(f"Saved {output} (HTTP {response.status})")

if __name__ == "__main__":
    asyncio.run(main())

Run it once before adding a schedule:

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

The filename includes a UTC timestamp, so repeated runs do not overwrite each other. Store the directory on persistent disk or upload each result to storage if the machine running cron is temporary.

Schedule with cron

For example, run every day at 08:30 UTC. Edit the crontab with crontab -e and add a line using the absolute paths for your installation:

30 8 * * * cd /opt/site-capture && TARGET_URL='https://example.com' /opt/site-capture/.venv/bin/python /opt/site-capture/capture.py >> /opt/site-capture/capture.log 2>&1

Cron uses the machine’s timezone unless configured otherwise. Verify the host timezone and daylight-saving behavior; if the run must align to UTC, configure the host or scheduler explicitly. Keep the script, browser installation, output path, and log path accessible to the cron user.

3. Use APITemplate.io for scheduled template images

If the scheduled output should be a designed graphic—such as a report cover, status card, or social image—create an image template in APITemplate.io, then have your scheduler submit JSON data to the v2 /create-image endpoint. This produces a template-based image; it does not establish that APITemplate.io captures a live webpage. The documented API uses a template ID, an X-API-KEY header, and JSON input. Create an APITemplate.io template · v2 request example and regional endpoints

cURL

curl -X POST 'https://rest.apitemplate.io/v2/create-image?template_id=YOUR_TEMPLATE_ID' \
  -H 'X-API-KEY: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"overrides":[{"name":"title","text":"Daily site report"}]}'

Replace title with the name of a text element in your image template. The response contains a result such as a download URL and status; inspect the response and handle unsuccessful generation in the calling job. See the current first-request docs for the current response shape.

Python

import os
import requests

endpoint = "https://rest.apitemplate.io/v2/create-image"
response = requests.post(
    endpoint,
    params={"template_id": os.environ["APITEMPLATE_TEMPLATE_ID"]},
    headers={
        "X-API-KEY": os.environ["APITEMPLATE_API_KEY"],
        "Content-Type": "application/json",
    },
    json={"overrides": [{"name": "title", "text": "Daily site report"}]},
    timeout=90,
)
response.raise_for_status()
result = response.json()
if result.get("status") != "success":
    raise RuntimeError(f"Image generation did not succeed: {result}")
print(result.get("download_url"))

Install the dependency with pip install requests. Set APITEMPLATE_TEMPLATE_ID and APITEMPLATE_API_KEY as environment variables or secret-store values. Do not commit credentials to the script or repository.

Node.js

const endpoint = new URL('https://rest.apitemplate.io/v2/create-image');
endpoint.searchParams.set('template_id', process.env.APITEMPLATE_TEMPLATE_ID);

const response = await fetch(endpoint, {
  method: 'POST',
  headers: {
    'X-API-KEY': process.env.APITEMPLATE_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    overrides: [{ name: 'title', text: 'Daily site report' }],
  }),
  signal: AbortSignal.timeout(90000),
});

if (!response.ok) {
  throw new Error(`APITemplate.io returned HTTP ${response.status}: ${await response.text()}`);
}
const result = await response.json();
if (result.status !== 'success') {
  throw new Error(`Image generation failed: ${JSON.stringify(result)}`);
}
console.log(result.download_url);

Set both environment variables in the scheduler’s secret configuration. Confirm that the runtime supports fetch and AbortSignal.timeout; on older Node versions, use an AbortController timeout instead.

Scheduling the APITemplate call

Use the same cron pattern, replacing the Playwright command with your Python or Node script. With n8n, use a Cron trigger followed by an HTTP Request node configured for POST, the v2 endpoint, the API key header, and the JSON request body. Add logging and an error branch before putting the workflow into regular use. APITemplate.io documents Cron-triggered recurring report generation in its n8n integration guide.

4. Configure a dependable live-page capture

Decision Practical default When to change it
Wait condition Wait for load, then a short delay Prefer a page-specific selector when content loads asynchronously. Network idle can never occur on pages with continuous polling.
Viewport Choose a fixed width and height Use separate runs for desktop and mobile comparisons; keep dimensions and device scale factor stable.
Full page Use full-page capture for long documents Use viewport-only shots for above-the-fold monitoring or very long pages that are expensive to render.
Authentication Use a dedicated test account and protected secrets Persist browser storage state only when needed, and restrict access because it can contain session credentials.
Output naming Host plus UTC timestamp Add environment, route, viewport, or run ID when monitoring multiple variants.
Retention Define a retention window and cleanup job Keep longer for audits or visual history; store sensitive captures in access-controlled storage.
Retries Retry transient navigation or infrastructure errors a small, bounded number of times Do not endlessly retry permanent HTTP errors, access denials, or invalid URLs.

For authenticated pages, avoid putting passwords directly in cron command lines, where they may be visible to local users or process inspection. Use environment secrets or a secret manager, and grant the capture account only the access it needs. A screenshot can contain personal or confidential information; limit storage access and retention accordingly.

5. Troubleshooting scheduled captures

Symptom Likely cause Fix
No file appears Cron has a different working directory, PATH, user, or Python environment Use absolute paths, set the working directory in the cron line, redirect logs, and run the exact command as the cron user.
Browser executable missing Playwright’s Chromium was installed for another user or environment Run playwright install chromium in the same environment and account used by the scheduled job.
Navigation timeout Slow site, blocked network, or an overly strict wait condition Check connectivity and logs, increase the timeout only as needed, and wait for a specific content selector rather than a page-wide idle condition.
Screenshot is blank or incomplete Content renders after the chosen wait, requires scrolling, or is hidden behind consent UI Wait for the relevant selector, test the site’s normal browser behavior, and account for lazy-loaded content. Do not assume a screenshot API will remove consent UI unless its documented behavior says so.
HTTP 401 or 403 Target requires authentication, blocks automation, or credentials expired Verify access policy and credentials. Do not attempt to bypass access controls or bot challenges.
APITemplate.io rejects the request Wrong API key, template ID, JSON format, or endpoint version Use the current v2 endpoint, check the header and template ID, and compare the request body with the v2 guide. Do not copy old v1 examples.
APITemplate.io returns a generation error Override element names or values do not match the template Check element names and supported properties in the template editor and inspect the API error response.
Runs overlap A previous capture takes longer than the schedule interval Prevent concurrent runs with a lock, increase the interval, or move jobs to a queue with a single-worker limit.

6. Performance, reliability, and cost

Self-hosted Playwright avoids a per-capture screenshot API charge, but it is not operationally free: budget for compute, browser installation and updates, storage, network egress, logs, and engineering time. Full-page captures and multiple viewport variants use more rendering time and disk space. Keep the browser version and capture settings stable if you compare images over time.

For reliability, record each run’s start time, target URL, final URL, HTTP status, duration, output path, and failure reason. Alert on missing runs as well as failed runs; a stopped scheduler otherwise looks like a quiet success. Make writes atomic where downstream jobs consume files, and use bounded retries for transient failures.

APITemplate.io is a separate template-generation service in this workflow. Check its current plan limits, generation behavior, regional endpoint and retention terms in its own documentation and account before estimating cost or data location. The current docs list regional v2 endpoints; choose the appropriate documented region if residency or latency matters. Current API and regional endpoint documentation

7. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. A single request captures a live URL as PNG, JPEG, WebP, or PDF. It removes cookie and consent banners, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status.

For a schedule, call the API from your existing cron job or workflow and save the response with a timestamp. This cURL example captures a page as WebP:

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

For parameter options and output configuration, see the ScreenshotNeo API documentation. Its MCP server also lets Claude, Cursor, and other MCP clients use take_screenshot, get_page_info, and capture_pdf. One thousand screenshots a month are free with no card; paid plans start at $5 for 3,000, and every feature is on every plan.

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

Frequently asked questions

Can APITemplate.io take a screenshot of any URL?

The current official materials reviewed here document image generation from templates and JSON. They do not verify arbitrary live-URL webpage capture. Confirm with APITemplate.io support or current documentation before relying on that capability.

Can I use APITemplate.io to create a screenshot on a schedule?

You can schedule a workflow that calls its documented template-generation API. That workflow creates a template-based image or document from data; it is not evidence of capturing a rendered webpage.

Does the scheduled time use UTC?

That depends on the scheduler and host configuration. Cron commonly follows the machine timezone, so set and verify the intended timezone explicitly.

Should I use a managed service or run a browser?

Run a browser when you need direct control over browser setup, timing, and storage. A managed screenshot API can remove browser operations from your code; check its capture options, storage, retention, authentication support, and failure behavior before selecting it.