Async jobs
Process screenshots asynchronously with webhooks
Async jobs
For long-running captures or when you don't want to wait for the response, use async jobs. The API immediately returns a job ID, and you can poll for status or receive a webhook when complete.
Create async job
POST /v1/screenshots/asyncRequest body
Same parameters as the screenshots endpoint, plus:
| Parameter | Type | Description |
|---|---|---|
webhookUrl | string | URL to receive completion notification |
webhookSecret | string | Secret for webhook signature verification |
outputs | array | Multi-output extraction. Request multiple formats from one page load. |
Example request
curl -X POST 'https://api.allscreenshots.com/v1/screenshots/async' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"url": "https://example.com",
"fullPage": true,
"webhookUrl": "https://your-server.com/webhooks/screenshot"
}'Response
{
"id": "abc123xyz0",
"status": "QUEUED",
"statusUrl": "https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0",
"createdAt": "2025-01-15T10:30:00Z"
}Get job status
GET /v1/screenshots/jobs/{jobId}Example request
curl 'https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0' \
-H 'X-API-Key: YOUR_API_KEY'Response (queued)
{
"id": "abc123xyz0",
"status": "QUEUED",
"url": "https://example.com",
"createdAt": "2025-01-15T10:30:00Z"
}Response (completed)
{
"id": "abc123xyz0",
"status": "COMPLETED",
"url": "https://example.com",
"resultUrl": "https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0/result",
"storageUrl": "https://storage.allscreenshots.com/abc123xyz0.png",
"createdAt": "2025-01-15T10:30:00Z",
"startedAt": "2025-01-15T10:30:01Z",
"completedAt": "2025-01-15T10:30:05Z",
"expiresAt": "2025-01-22T10:30:05Z",
"metadata": {
"width": 1920,
"height": 4500,
"format": "PNG",
"size": 245678
}
}Response fields
| Field | Type | Description |
|---|---|---|
id | string | Job ID |
status | string | QUEUED, PROCESSING, COMPLETED, FAILED, or CANCELLED |
url | string | Requested URL |
resultUrl | string | API URL for downloading the result when complete |
storageUrl | string | CDN URL for the stored result when available |
errorCode | string | Error code when the job failed |
errorMessage | string | Error message when the job failed |
createdAt | string | Creation timestamp |
startedAt | string | Processing start timestamp |
completedAt | string | Completion timestamp |
expiresAt | string | Result expiration timestamp |
metadata | object | Result metadata such as dimensions, format, and size |
outputs | object | Multi-output metadata when outputs was requested |
Response (failed)
{
"id": "abc123xyz0",
"status": "FAILED",
"url": "https://example.com",
"errorCode": "TIMEOUT",
"errorMessage": "Page load timed out after 60 seconds",
"createdAt": "2025-01-15T10:30:00Z",
"startedAt": "2025-01-15T10:30:01Z",
"completedAt": "2025-01-15T10:31:00Z"
}Response (completed with multi-output)
When the job was created with an outputs array, the completed response includes per-output details:
{
"id": "abc123xyz0",
"status": "COMPLETED",
"url": "https://example.com",
"resultUrl": "https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0/result/screenshot",
"storageUrl": "https://storage.allscreenshots.com/abc123xyz0/screenshot.png",
"createdAt": "2025-01-15T10:30:00Z",
"startedAt": "2025-01-15T10:30:01Z",
"completedAt": "2025-01-15T10:30:05Z",
"expiresAt": "2025-01-22T10:30:05Z",
"metadata": {
"width": 1920,
"height": 4500,
"format": "MULTI",
"size": 246878
},
"outputs": {
"screenshot": {
"type": "screenshot",
"contentType": "image/png",
"size": 245678,
"resultUrl": "https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0/result/screenshot",
"storageUrl": "https://storage.allscreenshots.com/abc123/screenshot.png"
},
"markdown": {
"type": "markdown",
"contentType": "text/markdown",
"size": 1200,
"resultUrl": "https://api.allscreenshots.com/v1/screenshots/jobs/abc123xyz0/result/markdown",
"storageUrl": "https://storage.allscreenshots.com/abc123/content.md"
}
}
}Get job result
Download the screenshot once the job is complete:
GET /v1/screenshots/jobs/{jobId}/resultThe response format depends on the responseType that was set when the job was created:
binaryorurl(default): returns the raw image binary with the appropriate content type header.base64: returns JSON with the image data encoded as a base64 string.
Binary result (default)
curl 'https://api.allscreenshots.com/v1/screenshots/jobs/job_abc123xyz/result' \
-H 'X-API-Key: YOUR_API_KEY' \
--output screenshot.pngBase64 result
If the job was created with responseType: "base64", the result endpoint returns JSON:
{
"url": "https://example.com",
"format": "png",
"contentType": "image/png",
"width": 1920,
"height": 1080,
"size": 245678,
"renderTimeMs": 4250,
"encoding": "base64",
"data": "iVBORw0KGgo..."
}Get specific output result
For multi-output jobs, download a specific output by its ID:
GET /v1/screenshots/jobs/{jobId}/result/{outputId}As with the main result endpoint, the response format depends on the responseType of the original job. With responseType: "base64", the response is JSON with base64-encoded data instead of raw binary.
# Get the markdown output
curl 'https://api.allscreenshots.com/v1/screenshots/jobs/job_abc123xyz/result/markdown' \
-H 'X-API-Key: YOUR_API_KEY'
# Get the screenshot output
curl 'https://api.allscreenshots.com/v1/screenshots/jobs/job_abc123xyz/result/screenshot' \
-H 'X-API-Key: YOUR_API_KEY' \
--output screenshot.pngJob results are available until the expiresAt timestamp. The default retention period is 7 days.
Job statuses
| Status | Description |
|---|---|
QUEUED | Job is queued for processing |
PROCESSING | Screenshot capture is in progress |
COMPLETED | Capture succeeded and the result is available |
FAILED | Capture failed; see errorCode and errorMessage |
CANCELLED | Job was cancelled before processing |
Polling vs webhooks
Polling
Simple to implement but less efficient:
async function waitForJob(jobId) {
while (true) {
const response = await fetch(
`https://api.allscreenshots.com/v1/screenshots/jobs/${jobId}`,
{ headers: { 'X-API-Key': API_KEY } }
);
const job = await response.json();
if (job.status === 'COMPLETED') {
return job.resultUrl;
}
if (job.status === 'FAILED') {
throw new Error(job.errorMessage);
}
await new Promise(resolve => setTimeout(resolve, 1000));
}
}Webhooks (recommended)
More efficient—no polling required:
// Create job with webhook
const response = await fetch('https://api.allscreenshots.com/v1/screenshots/async', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com',
webhookUrl: 'https://your-server.com/webhooks/screenshot',
webhookSecret: 'your-webhook-secret',
}),
});
// Handle webhook in your server
app.post('/webhooks/screenshot', (req, res) => {
// Verify signature (see Webhooks docs)
const job = req.body;
if (job.status === 'COMPLETED') {
console.log('Screenshot ready:', job.data.resultUrl);
}
res.sendStatus(200);
});See Webhooks for complete webhook documentation.
Use cases
Async jobs are ideal for:
- Full page captures: Pages that take longer to render
- Batch processing: When combined with bulk jobs
- Background tasks: When you don't need immediate results
- Long timeouts: Pages with heavy JavaScript or slow loading assets
Example workflow
// 1. Create async job
const { id: jobId } = await createAsyncJob({
url: 'https://example.com/report',
fullPage: true,
waitUntil: 'networkidle',
});
// 2. Store job ID in your database
await db.screenshots.create({
jobId,
url: 'https://example.com/report',
status: 'PROCESSING',
});
// 3. Process webhook when complete
app.post('/webhooks/screenshot', async (req, res) => {
const { jobId, status, resultUrl, errorMessage } = req.body.data;
await db.screenshots.update(jobId, {
status,
screenshotUrl: resultUrl,
error: errorMessage,
});
res.sendStatus(200);
});