Website Screenshot API With Webhook Support for Completed Captures
Learn how async screenshot jobs and completion webhooks work, what to verify before choosing a provider, and how to build a reliable callback handler.
A website screenshot API with webhook support accepts a capture request, renders the page in a hosted browser, and sends your application a completion notification when the result is ready. The request usually returns a job or render ID first; the callback arrives later. The exact request fields, callback payload, signature, retry behavior, and result retrieval method vary by provider, so verify the current contract before you build around it.
ScreenshotNeo supports asynchronous jobs with signed webhooks as well as polling. Its webhook documentation describes retries after 2, 15, and 60 seconds with the same delivery ID. These are ScreenshotNeo-specific details, not a shared standard for screenshot APIs. See the ScreenshotNeo API documentation.
1. How screenshot completion webhooks work
A synchronous API keeps the request open while the browser loads and captures the page. An asynchronous API accepts the work and responds before rendering is finished. Your application then gets the result through a callback, a status-polling endpoint, or both.
- Your service submits a URL and capture options, plus an async setting and callback URL when required.
- The screenshot provider accepts or queues the job and returns an acknowledgement, often with a job ID.
- A hosted browser loads the page and creates the requested output, such as a PNG, JPEG, WebP, or PDF where supported.
- The provider sends an HTTP POST to your callback URL when processing reaches a documented completion state.
- Your handler authenticates the callback, records it idempotently, and stores or retrieves the result using the provider’s documented method.
Do not assume every provider sends callbacks for failures, returns the image in the callback body, or keeps result files for the same length of time. Confirm those details for the selected service.
2. Choose a provider by its completion contract
A “webhooks supported” checkbox is not enough to assess whether an integration will work for your application. Compare the actual contract and operational limits.
| Question | What to verify |
|---|---|
| Is it available? | Confirm async callbacks are enabled for the deployment, account, and plan you will use. The screenshotapis.org guide currently reports that callbacks are unavailable on its reviewed deployment and async callback requests return 503 without charging a credit. That is a deployment-specific notice, not a statement about all screenshot APIs. Source |
| What does acceptance mean? | Identify the immediate HTTP status, job ID, and whether acceptance means queued, started, or completed. |
| What events arrive? | Check success and failure event types, payload fields, and whether a callback includes the image, a temporary URL, or only an ID. |
| How do I get the result? | Determine whether to download a URL, call a retrieval endpoint, or use a configured storage destination. ScreenshotOne documents an S3 upload result workflow. ScreenshotOne async and webhook docs |
| How are deliveries authenticated? | Read which exact bytes or fields are signed, which secret is used, how timestamps work, and how to reject replays. Signature schemes differ between providers. |
| What happens when delivery fails? | Check timeouts, retry schedule, stable event or delivery IDs, ordering behavior, and whether jobs can be polled as a recovery path. |
| What are the limits and costs? | Check quotas, rate and concurrency limits, output format pricing, storage or egress charges, and result retention in current plan documentation. |
Examples in provider documentation illustrate different interfaces rather than a universal format. ScreenshotOne documents async rendering and webhook POST delivery; Screenshotor documents queueing with a webhookUrl and polling; ScreenshotNeo documents signed webhooks and job polling. Consult each provider’s own current docs before adapting an example: ScreenshotOne, Screenshotor, and ScreenshotNeo.
3. Build a dependable webhook receiver
The callback handler should acknowledge quickly after authenticating and durably recording the event. Move expensive image downloads, transformations, and downstream work to a queue. This makes provider timeouts less likely and lets your workers retry independently.
- Expose an HTTPS endpoint. Make it reachable from the provider’s delivery system. Use the callback URL format and any network allowlisting the provider documents.
- Read the raw request body. Some signature schemes cover the exact raw bytes. Parsing and reserializing JSON can change whitespace or property ordering and invalidate verification.
- Verify authenticity before acting. Use the provider’s documented signature header, input string, secret, digest, and timestamp rules. Compare signatures using a constant-time method where applicable. Reject timestamps outside the documented replay window if the scheme has timestamps.
- Validate the event shape. Check the event type, job or render ID, required fields, and expected account context. Treat result URLs as untrusted input and follow your application’s SSRF and download restrictions.
- Deduplicate and persist. Insert the provider’s stable delivery/event ID under a uniqueness constraint, or use the documented job and event identity. Persist the validated payload and enqueue follow-up work in the same transaction when possible.
- Return a success response promptly. Follow the provider’s accepted status codes and timeout. If persistence fails, return a retryable error so a provider that retries can deliver again.
- Recover with polling. Reconcile jobs that remain pending beyond your expected processing window using the provider’s status endpoint, if available.
Idempotency and duplicate deliveries
Assume a callback may be delivered more than once unless the provider explicitly documents a stronger guarantee. A timeout can happen after your server commits the event but before the provider receives your response; the provider may retry. Store a delivery ID or other documented event key and make processing safe to repeat. Do not mark a job complete twice in a way that triggers duplicate billing, notifications, or downstream work.
Ordering and terminal states
Do not assume callbacks arrive in order. Define allowed state transitions, such as queued → rendering → succeeded or failed, and make terminal states resistant to stale updates. If the provider’s payload has no sequence number, query job status before applying an event that conflicts with a previously recorded terminal result.
4. Request and retrieve an asynchronous capture
There is no cross-provider runnable request that can be substituted unchanged: async flags, callback URL parameters, authentication, job response fields, callback payloads, and polling endpoints differ. Use the selected provider’s current example and map it into this flow:
POST provider capture endpoint
authentication: provider-specific
capture options: URL and output settings
async option: provider-specific
callback URL: https://your.example.com/hooks/screenshot
Read acknowledgement:
job_id = provider-specific response field
On callback:
verify provider-specific signature over documented input
deduplicate using documented delivery/event ID
inspect success/failure event and result fields
retrieve or store output using documented method
If callback is not received:
poll provider-specific status endpoint with job_id
Keep secrets on the server. Do not put API credentials or webhook signing secrets into browser JavaScript, public callback query strings, or logs. Use a unique secret per environment where the provider supports it, and rotate it using the provider’s documented procedure.
ScreenshotNeo example: one-call capture
ScreenshotNeo can return an image from one GET request. Its API also supports async jobs with signed webhook delivery when you need completion callbacks; see the API docs for the exact async parameters, payload, and signature verification contract. The following is the documented synchronous one-call form, useful when a callback is not needed:
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}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
The Node.js example uses the documented request with a Bun file-write helper. In a Node.js application, write the response bytes using your chosen filesystem API, and check the response status and content type before treating the body as an image.
5. Security and privacy details
- Use HTTPS for callbacks and verify the provider’s signature; a hard-to-guess URL alone does not authenticate a sender.
- Verify signatures against the precise raw body or signed input in the provider’s specification. Do not reuse another vendor’s HMAC recipe.
- Apply timestamp freshness checks only as specified by the scheme; retain enough tolerance for documented clock skew while rejecting stale replays.
- Keep API keys and signing secrets in server-side secret storage. Redact them from request logs and exception reports.
- Limit callback body size and validate content types, fields, and result URL hosts. Avoid blindly fetching arbitrary URLs supplied in an event.
- Review what page content is sent to a hosted browser, how results are stored, who can access result links, and the provider’s retention terms.
6. Reliability, latency, and cost
Latency and throughput
Async jobs free your request handler from waiting for a browser render, but they do not make the render itself faster. End-to-end completion includes queue delay, page load, capture, result storage, and callback delivery. Measure those stages in your own integration rather than relying on unverified cross-provider benchmarks. Set a job deadline based on your application needs and provider limits.
Use a bounded worker queue for result processing. Set concurrency according to the provider’s documented limits and your own storage/download capacity. Avoid rapid polling: follow the provider’s recommended interval and use backoff if no interval is specified.
Failure recovery
Record the submission time, provider job ID, last known state, callback attempts you observe, and final outcome. Alert on jobs that remain pending too long, repeated signature failures, callback endpoint errors, and result downloads that fail. Retain enough metadata to reconcile missing callbacks through polling where available.
Callbacks are a notification channel, not proof that your processing completed. A provider may retry after a lost response, and your own database or worker can fail after receipt. Durable event storage, idempotent workers, and a polling reconciliation path make the application more resilient.
Cost accounting
Compare the billable unit and included quota for successful captures, plus costs for output types, storage, transfers, and any retries charged by the provider. Ask what happens to a failed render, a cache hit, or a job whose callback cannot be delivered. These are plan-specific terms and can change; confirm current pricing and quota pages before estimating production spend.
ScreenshotNeo states that only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, with response headers indicating page verdict and billing status. Its listed plans are Free for 1,000 shots per month with no card; Starter $5 for 3,000; Growth $15 for 15,000; Pro $39 for 60,000; Scale $99 for 250,000; and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Confirm current terms on the product site before purchasing.
7. Troubleshooting common webhook problems
| Symptom | Likely cause | What to do |
|---|---|---|
| Capture request returns an error before a job is created | Async callbacks are disabled on that deployment, plan, or account, or the request options are invalid. | Check the provider’s current availability notice and request schema. Do not assume a job exists unless the response contract confirms acceptance. |
| Job is accepted but callback never arrives | Callback URL is unreachable, TLS or DNS is invalid, a firewall blocks delivery, or the provider reports only certain event types. | Inspect provider delivery logs if available, verify public HTTPS reachability, and use polling to recover if supported. |
| Signature verification fails consistently | Handler parsed and reserialized JSON, used the wrong secret/header, or followed a different provider’s signature scheme. | Capture the raw bytes, check the exact signed input and encoding in the selected provider’s docs, and test against its example vector if provided. |
| Signature fails intermittently | Timestamp parsing, clock skew, body mutation in middleware, or secret rotation mismatch. | Check server clock synchronization, verify middleware preserves raw bytes, and confirm active secret and timestamp rules. |
| Duplicate work occurs | Provider retried after a timeout or the receiver processed the same event more than once. | Persist a stable provider delivery/event ID with a uniqueness constraint and make downstream actions idempotent. |
| Callback returns success but image is missing | The callback may contain metadata only, a temporary URL may have expired, or retrieval was attempted before the provider’s documented availability point. | Follow the payload’s documented retrieval method and retention window; copy results to your storage promptly when required. |
| Webhook retries stop after repeated errors | The provider has a finite retry policy or the receiver exceeded its timeout. | Return the expected success code quickly after durable receipt, move long work to a queue, and reconcile missing jobs through polling. |
| A callback changes a completed job back to pending | Events arrived out of order or stale state overwrote a terminal state. | Enforce state transitions and use event sequence/version information if documented; otherwise reconcile with the status endpoint. |
8. Or skip the browser setup
With ScreenshotNeo, a single GET request can return a screenshot, while its async jobs support signed completion webhooks and polling. Cookie banners, newsletter popups, and chat widgets are removed before the shot; each cleanup step can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are never billed. An MCP server lets AI agents using Claude, Cursor, or another MCP client take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For async capture parameters and signed webhook handling, use the ScreenshotNeo docs. Sign up for 1,000 free screenshots a month with no card.
9. Frequently asked questions
Does every website screenshot API support completion webhooks?
No. Availability varies by provider and deployment. For example, the screenshotapis.org guide reports callbacks unavailable on the deployment it documents, while ScreenshotOne, Screenshotor, and ScreenshotNeo document async callback workflows. Verify the actual account and deployment you plan to use.
Should I use a webhook or poll for completion?
Use a webhook to receive prompt notifications without repeatedly checking status. Keep polling as a recovery mechanism when the provider offers it, because callbacks can be delayed or missed.
Can I treat a successful callback as proof the file is permanent?
No. A success event and result retention are separate contract details. Check how to retrieve the output and how long any hosted result remains available.
Can I reuse one webhook implementation for several providers?
You can share internal concepts such as event persistence and idempotent processing, but keep provider-specific adapters for request fields, signature verification, payload parsing, retry assumptions, and result retrieval.


