ScreenshotNeo

BlogHow-to

Can Microlink Take Recurring Screenshots of a Website?

Microlink can capture screenshots through its API, but recurring captures need an external scheduler. Here’s how to set up a reliable workflow.

By the ScreenshotNeo team4 October 202611 min read

Yes, Microlink can capture website screenshots, but the official documentation reviewed for this guide does not describe a built-in recurring schedule. To take screenshots on a cadence, use an external scheduler or an application timer to call Microlink’s screenshot API, then save or process the returned image asset. The scheduler, retries, alerts, and retention are part of your surrounding workflow.

Microlink’s screenshot API accepts a target URL and screenshot options, renders the page in a browser, and returns screenshot asset metadata, including a hosted image URL. The JavaScript SDK also has a screenshot method. You can call the HTTP API directly if you do not want to use the SDK. See the Microlink screenshot documentation and its guide to dynamic pages.

1. Choose the schedule and capture policy

Before writing the job, decide what “recurring” means for your use case. A page you check hourly needs a different quota and retention plan than a weekly archive.

  • Cadence and timezone: choose an interval and specify the timezone your scheduler uses. Prefer UTC for a job that should not shift during daylight-saving changes.
  • Capture target: choose the exact URL, viewport or full-page behavior, and image format your workflow needs.
  • Page readiness: identify a stable selector that appears when the content you need is ready. Dynamic pages may need a readiness condition or interaction.
  • Storage and retention: decide whether to download each image, keep the returned hosted asset URL, or send it to another system. Set a retention period appropriate to the purpose.
  • Failure behavior: decide how to retry transient errors, where to report persistent failures, and how to prevent overlapping runs.
  • Comparison: if you need visual change detection, compare image files after capture; recurring capture by itself does not establish that a page changed.

Microlink’s product page advertises monitoring as a use case, but that does not establish that the screenshot API has a native recurring scheduler. Treat the external trigger as your scheduling layer.

Start by making one successful capture manually. The API endpoint is https://api.microlink.io. Pass the target page as url and enable screenshot. Microlink’s guide describes these as the two required parameters for a screenshot request.

cURL

curl -G 'https://api.microlink.io' \
  --data-urlencode 'url=https://example.com' \
  --data 'screenshot=true' \
  --data 'meta=false'

This returns JSON containing screenshot metadata. The response includes a hosted asset URL along with values such as the image dimensions, type, and size. If you want the endpoint to return the image itself, use Microlink’s documented embed option for the screenshot URL; see its screenshot parameter documentation for the current syntax.

Python

import requests

response = requests.get(
    "https://api.microlink.io",
    params={
        "url": "https://example.com",
        "screenshot": "true",
        "meta": "false",
    },
    timeout=90,
)
response.raise_for_status()

payload = response.json()
if payload.get("status") != "success":
    raise RuntimeError(f"Microlink capture failed: {payload}")

screenshot = payload["data"]["screenshot"]
print("Screenshot URL:", screenshot["url"])
print("Image type:", screenshot.get("type"))
print("Dimensions:", screenshot.get("width"), "x", screenshot.get("height"))

Node.js

const params = new URLSearchParams({
  url: 'https://example.com',
  screenshot: 'true',
  meta: 'false',
});

const response = await fetch(`https://api.microlink.io/?${params}`);
if (!response.ok) {
  throw new Error(`Microlink HTTP error: ${response.status}`);
}

const payload = await response.json();
if (payload.status !== 'success') {
  throw new Error(`Microlink capture failed: ${JSON.stringify(payload)}`);
}

const screenshot = payload.data.screenshot;
console.log('Screenshot URL:', screenshot.url);
console.log('Image type:', screenshot.type);
console.log('Dimensions:', screenshot.width, 'x', screenshot.height);

3. Run the request on a schedule

Connect the working request to a scheduler you already operate: a system cron, a hosted workflow scheduler, or a timer in your own application. The following cron entry runs a Python script every day at 02:15 UTC. Install requests in the environment that runs the job and save the Python example below as capture.py.

Runnable scheduled Python script

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

import requests

TARGET_URL = os.environ.get("TARGET_URL", "https://example.com")
OUTPUT_DIR = Path(os.environ.get("OUTPUT_DIR", "captures"))
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

response = requests.get(
    "https://api.microlink.io",
    params={"url": TARGET_URL, "screenshot": "true", "meta": "false"},
    timeout=90,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "success":
    raise RuntimeError(f"Microlink capture failed: {json.dumps(payload)}")

asset = payload["data"]["screenshot"]
image_response = requests.get(asset["url"], timeout=30)
image_response.raise_for_status()

stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
extension = asset.get("type", "jpg").lower()
output_path = OUTPUT_DIR / f"capture-{stamp}.{extension}"
output_path.write_bytes(image_response.content)
print(f"Saved {output_path} ({len(image_response.content)} bytes)")
# Run daily at 02:15 UTC. Set TARGET_URL and OUTPUT_DIR in the job environment.
15 2 * * * /usr/bin/python3 /path/to/capture.py

Set an explicit timezone in the scheduler configuration if it supports one. Cron’s timezone behavior depends on the host and its configuration, so confirm the host timezone rather than assuming it is UTC. For a workflow scheduler, use the same request and file-handling steps in its scheduled job, and configure its timezone, retry policy, and failure notification there.

Why download the asset?

The response contains a hosted screenshot URL. If your archive must remain under your control for a known period, download the asset into storage you manage instead of relying on a URL as your only record. If you only need to pass the image to another step, retaining the asset URL may be enough. Confirm the vendor’s current asset retention behavior if your workflow depends on long-term availability.

4. Handle dynamic pages before capture

A page can return a successful request and still produce an unhelpful screenshot if its client-rendered content has not appeared. Microlink documents waitUntil, waitForSelector, waitForTimeout, scroll, and click controls for page readiness and interaction. The dynamic-content guide recommends waiting for a meaningful selector when possible; fixed delays may waste time on fast loads and still be too short on slow ones.

For example, add a readiness selector to the cURL request when the report chart is the content that must be present:

curl -G 'https://api.microlink.io' \
  --data-urlencode 'url=https://example.com/report' \
  --data 'screenshot=true' \
  --data 'meta=false' \
  --data 'waitUntil=domcontentloaded' \
  --data-urlencode 'waitForSelector=.chart svg'

Use the equivalent query parameters in Python or Node.js by adding waitUntil and waitForSelector to the request’s parameter object. Choose a selector that reflects the content state you care about, not merely a generic page shell. If content only loads when scrolled into view, use the documented scroll control and wait for an element inside the lazy section. If a click is required to reveal a panel, use the documented click control and wait for the resulting content.

Relevant screenshot options

The documented screenshot options include full-page capture and image type; the API guide also describes options such as element selection, quality, and overlay. Page preparation options include lifecycle waits, selector waits, timeout waits, scroll, and click. Consult the current screenshot parameter reference and browser automation guide for accepted values and exact syntax before adding options to a production job.

  • Viewport or full page: use a viewport shot when the visible fold is sufficient; use full-page capture when the archive needs the whole document.
  • Format and quality: choose an image type and quality that fit the downstream consumer and storage budget. Larger images take more space and time to transfer.
  • Element capture: target a specific element when the rest of the page is irrelevant; ensure it exists and is visible at capture time.
  • Readiness: prefer a selector or appropriate lifecycle event over a long fixed delay. Avoid waiting for network silence on pages that keep long-lived connections open.
  • Interactions: scroll or click only when the target page requires it, then wait for the resulting state.

5. Make the recurring job reliable

One-off request success is not enough for a recurring workflow. Treat every run as a small job with a clear outcome, logs, and bounded failure handling.

  1. Check both transport and API status. Raise on HTTP errors and validate the JSON status and screenshot field before storing an image.
  2. Use bounded retries. Retry transient connection failures and server errors with exponential backoff and a small maximum attempt count. Do not retry permanent invalid-URL or authentication errors indefinitely.
  3. Prevent overlapping captures. If a run takes longer than the interval, use a scheduler lock or application-level lease so two runs do not write the same destination or overwhelm the workflow.
  4. Use unique filenames. Timestamp each capture in UTC, and include a stable page identifier if one job handles multiple URLs.
  5. Log useful metadata. Record run time, target URL, response status, asset URL, dimensions, duration, and final storage path. Avoid logging secrets or sensitive query parameters.
  6. Alert on persistent failures. Send an alert after retries are exhausted, and include enough context to diagnose the failed target without exposing credentials.
  7. Test the actual schedule. Confirm the scheduler timezone, environment variables, network access, and storage permissions in the runtime that will execute the job.

For a monitored set of many pages, consider staggering jobs and enforcing a concurrency limit. This reduces synchronized traffic spikes and makes it easier to stay within request quotas.

6. Performance, quota, and cost

Capture frequency multiplies request volume. A single URL captured every 15 minutes produces 96 captures per day; 10 URLs at that cadence produce 960. Count scheduled attempts, including retries, when estimating usage. Full-page captures and long page-readiness waits can take longer or produce larger files than a simple viewport capture.

Microlink’s official screenshot guide and product page currently describe 25 free requests per day and say the API can be used without an API key. These are vendor-published terms and can change, so check the current plan limits before setting a production cadence. The dynamic-content guide lists request timeouts of 30 seconds for the free plan and 60 seconds for Pro; verify those limits against current plan terms, and keep your own client timeout long enough to receive a response.

  • Use meta=false when you only need the screenshot, as Microlink documents this as a way to skip metadata extraction.
  • Use the narrowest capture (viewport or element) that answers your question.
  • Choose a cadence based on how quickly the page can meaningfully change, not an arbitrary high frequency.
  • Keep retries bounded so a prolonged outage does not multiply request volume without limit.
  • Budget archive storage separately: even when API quota is adequate, image retention accumulates over time.

7. Troubleshooting

Symptom Likely cause What to do
The job runs, but the screenshot shows a loading shell. Client-rendered content was not ready when capture occurred. Wait for a meaningful selector with waitForSelector, or select a suitable waitUntil event. Use a fixed delay only when no stable state condition exists.
The page times out intermittently. The page is slow, an overly strict wait never completes, or the request timeout is too short. Use a selector for the required content, remove unnecessary waits, and keep all waits within the plan’s request timeout. Investigate whether the page’s selected element appears on every run.
The capture misses content farther down the page. Content is lazy-loaded only after scrolling, or a viewport screenshot was requested. Use full-page capture when appropriate; for lazy content, use the documented scroll control and wait for the relevant element.
A recurring run succeeds but no local image appears. The script kept only the API response or asset URL and did not download the image. Fetch the returned screenshot URL and write the response bytes to your chosen storage, as in the scheduled Python example.
The scheduler fires at the wrong local time. The scheduler host or workflow uses a different timezone, or daylight-saving time changed the local offset. Set and verify the scheduler timezone. Use UTC if the schedule should remain fixed year-round.
Usage runs out earlier than expected. Cadence, number of URLs, and retry attempts were not included in the request estimate. Calculate captures per day as URLs × (1440 ÷ interval in minutes), then add bounded retries and compare with the current plan quota.
Two captures overwrite one another. The output name is fixed or simultaneous runs share a destination. Use UTC timestamps or unique job identifiers and configure a lock or concurrency limit.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. For recurring captures, your scheduler still triggers each request, while ScreenshotNeo handles the browser capture. Its clean-shot flow accepts cookie and consent banners like a visitor and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Only clean shots are billed: bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with the result identified in response headers.

One request returns an image or PDF; available options include full-page capture with lazy images loaded, CSS element capture, viewport presets, dark mode, custom CSS and JavaScript, wait conditions, request blocking, headers and cookies, caching, and asynchronous jobs. The MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. See the ScreenshotNeo 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}`);

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

Frequently asked questions

The official materials reviewed describe screenshot requests and SDK methods, not a built-in recurring schedule. Trigger captures from a scheduler or application timer.

Do I need the JavaScript SDK?

No. The screenshot API can be called over HTTP, so cron scripts and other scheduled systems can make requests without the SDK.

Can I use recurring captures to detect changes?

Yes, as a workflow design: store each capture and compare it with a previous one using your chosen image comparison process. A screenshot service request alone does not define comparison thresholds or decide which differences matter.

Is the free request allowance enough?

That depends on the number of URLs, interval, and retries. The currently published allowance is 25 requests per day; verify current terms and calculate the scheduled volume before relying on it.