ScreenshotNeo

BlogGuides

PagePeeker Webhook Support for Completed Screenshot Jobs

PagePeeker’s public API documents readiness polling, not completion webhooks. Here’s how to check for a ready thumbnail and handle the result.

By the ScreenshotNeo team4 October 20268 min read

Does PagePeeker support webhooks when a screenshot job is complete? Its public API documentation describes checking a readiness endpoint and retrieving the image when it is ready. It does not document a webhook or callback URL for completion. That means webhook support is not established by the public documentation reviewed; it does not rule out an account-specific or undocumented option. If push notification is required, ask PagePeeker support directly.

For a documented integration, use readiness polling: initiate or refresh thumbnail generation, check thumbs_ready.php until the thumbnail is ready or an error is reported, then retrieve it. Each readiness check counts as an API call. PagePeeker API documentation · PagePeeker FAQ

What the public documentation establishes

  • PagePeeker identifies API V2 as its current recommended version; V1 is discontinued and redirects to V2.
  • The documented completion mechanism is a client-side readiness check. The documentation reviewed does not specify webhook events, callback registration, payloads, signing, or retry behavior.
  • The ready-check response includes Error and IsReady. The documented values are Error: 1 for an error creating the thumbnail and Error: 0 otherwise; IsReady: 1 means available and IsReady: 0 means not yet available.
  • Each readiness check adds one API call. PagePeeker distinguishes API calls from renders; after rendering, the thumbnail is cached on its servers for several days.

These facts support a pull workflow, where your application checks readiness. They do not confirm a push workflow, where PagePeeker calls your endpoint. Premium snapshots may be available on demand or on a schedule, but that is not documentation of completion webhooks.

Use the documented readiness-polling workflow

Keep this integration on your server. PagePeeker says its REST APIs are intended for server-side use. A code parameter is optional and recommended for server-side calls; do not expose it in a browser page, where third-party use could count against your monthly quota.

  1. Use the V2 API to request or refresh a thumbnail for the target URL and size, following the current endpoint and parameters in the official API documentation.
  2. Call the documented thumbs_ready.php readiness endpoint with the size, URL, and optional server-side API code.
  3. If Error is 1, stop polling and handle the creation error. If IsReady is 0, wait and check again. If IsReady is 1, retrieve the thumbnail.
  4. Set a deadline and a maximum number of checks. Persist the job state so a process restart does not lose track of the request.

The API documentation’s response fields and endpoint sequence are the contract to build around. Confirm exact request URLs, parameter spelling, and image retrieval URL in the current documentation before deploying; the code below intentionally leaves those provider-specific values as configuration rather than guessing them.

Server-side polling pattern in Python

import os
import time
import requests

API_CODE = os.environ.get("PAGEPEEKER_CODE")  # Optional; keep server-side.
SOURCE_URL = "https://example.com/"
SIZE = ""  # Set the size value required by your PagePeeker plan/API.

# Set these from the current PagePeeker V2 API documentation.
START_OR_REFRESH_URL = os.environ["PAGEPEEKER_START_URL"]
READY_URL = os.environ["PAGEPEEKER_READY_URL"]
IMAGE_URL = os.environ["PAGEPEEKER_IMAGE_URL"]

session = requests.Session()
params = {"url": SOURCE_URL, "size": SIZE}
if API_CODE:
    params["code"] = API_CODE

# Start or refresh capture using the documented V2 request.
start = session.get(START_OR_REFRESH_URL, params=params, timeout=20)
start.raise_for_status()

# Poll within a bounded deadline. Each readiness check counts as an API call.
deadline = time.monotonic() + 120
interval_seconds = 5
while time.monotonic() < deadline:
    ready = session.get(READY_URL, params=params, timeout=20)
    ready.raise_for_status()
    state = ready.json()

    if state.get("Error") == 1:
        raise RuntimeError("PagePeeker reported an error creating the thumbnail")
    if state.get("IsReady") == 1:
        image = session.get(IMAGE_URL, params=params, timeout=30)
        image.raise_for_status()
        with open("thumbnail.jpg", "wb") as output:
            output.write(image.content)
        break
    time.sleep(interval_seconds)
else:
    raise TimeoutError("Thumbnail was not ready before the polling deadline")

This is an integration pattern, not a copy-paste endpoint recipe: set the three endpoint environment variables and size according to PagePeeker’s current V2 documentation. Do not treat a successful HTTP status alone as completion; inspect both documented JSON fields.

cURL readiness check

Use the documented ready endpoint and parameter names from PagePeeker’s V2 reference. Keep any API code in a server environment rather than embedding it in client-side code.

curl --get "$PAGEPEEKER_READY_URL" \
  --data-urlencode "url=https://example.com/" \
  --data-urlencode "size=$PAGEPEEKER_SIZE" \
  --data-urlencode "code=$PAGEPEEKER_CODE"

Node.js polling pattern

import { setTimeout as delay } from "node:timers/promises";
import { writeFile } from "node:fs/promises";

const sourceUrl = "https://example.com/";
const size = process.env.PAGEPEEKER_SIZE ?? "";
const code = process.env.PAGEPEEKER_CODE;
const startUrl = process.env.PAGEPEEKER_START_URL;
const readyUrl = process.env.PAGEPEEKER_READY_URL;
const imageUrl = process.env.PAGEPEEKER_IMAGE_URL;

function makeParams() {
  const params = new URLSearchParams({ url: sourceUrl, size });
  if (code) params.set("code", code);
  return params;
}

async function get(url, params) {
  const response = await fetch(`${url}?${params}`, { signal: AbortSignal.timeout(20000) });
  if (!response.ok) throw new Error(`HTTP ${response.status} from PagePeeker`);
  return response;
}

await get(startUrl, makeParams());
const deadline = Date.now() + 120_000;
while (Date.now() < deadline) {
  const response = await get(readyUrl, makeParams());
  const state = await response.json();
  if (state.Error === 1) throw new Error("PagePeeker reported a thumbnail creation error");
  if (state.IsReady === 1) {
    const image = await get(imageUrl, makeParams());
    await writeFile("thumbnail.jpg", Buffer.from(await image.arrayBuffer()));
    break;
  }
  await delay(5000);
}
if (Date.now() >= deadline) throw new Error("Thumbnail polling deadline exceeded");

Polling frequency, state, and operational safeguards

Because each readiness check counts as an API call, avoid tight loops. Choose an interval appropriate to your job latency and quota, add a deadline, and stop on the documented error state. A fixed interval is simple; exponential backoff with a maximum interval can reduce calls when jobs take longer. Add small random jitter when many jobs poll together to avoid synchronized bursts.

Observed state Action
Error: 1 Stop polling, record the URL and response, and surface a capture failure for investigation or retry policy.
Error: 0, IsReady: 0 Wait, then check again while within the job deadline.
Error: 0, IsReady: 1 Retrieve and store the thumbnail; mark the job complete only after retrieval succeeds.
Malformed response or request failure Record status and response safely, apply bounded retry for transient network/server failures, and keep the job pending or failed according to your policy.

For paid and unbranded accounts, the API documentation lists response headers with capture method, capture time, final URL, capture hash, timestamp, and error state. Capture these when available to help diagnose redirects, stale results, and failures. Do not assume those headers exist for every account type.

When you specifically need a webhook

Ask PagePeeker support whether your account has an undocumented or account-specific completion callback. Make the question concrete:

  • Can a completed thumbnail job POST to a customer URL, or is readiness polling the only supported completion mechanism?
  • If callbacks exist, what are the event payload, authentication or signature scheme, retry schedule, delivery timeout, and duplicate-delivery behavior?
  • Can the callback distinguish capture errors from a successful ready thumbnail, and does it include the final URL or image location?
  • Does the answer differ between standard thumbnails and premium full-page or scheduled snapshots?

PagePeeker’s separate premium snapshot offering describes on-demand and scheduled snapshots, with guidance that weekly or more frequent scheduling may suit some uses and more than once a day is generally not advisable. That scheduling guidance does not promise a completion event. Its full-page options include custom page width and maximum captured height, compression, thumbnail size, overlay text, and wait behavior.

Common problems and fixes

Problem Likely cause What to do
Still not ready The page has not finished rendering, or polling began before generation completed. Continue at a measured interval until the deadline; verify the initial V2 request and URL/size values.
Error is 1 PagePeeker reports an error creating the thumbnail. Stop the readiness loop, log the response and relevant metadata, and retry only under a bounded policy.
API usage rises unexpectedly Each readiness check counts as an API call; an aggressive interval multiplies checks. Increase the interval, cap attempts, and avoid polling after completion or deadline.
API code appears in browser traffic The optional code was placed in client-side JavaScript or markup. Move calls to your server and keep the code in an environment variable or secret store.
Image is old or unexpected Rendered thumbnails are cached for several days, or the target redirects. Check whether the request refreshed generation as intended; inspect final URL and timestamp headers when available.
Site is not captured The site owner may block PagePeeker’s crawler. For a site you control, inspect robots.txt for a User-agent: PagePeeker rule and adjust it if appropriate.

Performance, reliability, and cost

Polling trades implementation simplicity for repeated requests. Its API-call cost scales with the number of checks per job, not just the number of thumbnails rendered. Use a moderate interval, bounded retries, and persisted state; retrieve the image once readiness is confirmed. PagePeeker says generated thumbnails are cached for several days, which can avoid repeated rendering, but the FAQ still counts each readiness check as an API call.

There is no webhook delivery guarantee in the public material reviewed, and no basis here for claims about service speed or uptime. Treat polling timeout, capture error, and image retrieval failure as separate states in your own job system. If a completion callback is essential, obtain a direct answer from support before designing around it.

Or skip the browser setup

For a one-call screenshot API, ScreenshotNeo returns a screenshot or PDF from a URL. Its clean-shot flow accepts cookie and consent banners and removes 60+ known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and responses report the page verdict and billing status. It also provides an MCP server with take_screenshot, get_page_info, and capture_pdf for AI agents.

cURL:

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

Python:

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)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

FAQ

Does PagePeeker’s API return a completion event?

The public API documentation reviewed describes readiness polling. It does not document a completion event or webhook.

Does PagePeeker block its crawler when a site asks it to?

PagePeeker says site owners can disallow its crawler in robots.txt with a User-agent: PagePeeker rule.

Are readiness checks free because no image is returned?

No. PagePeeker’s FAQ says each availability check counts as an API call, whether or not the thumbnail is ready.