Introducing Async Scan Polling: Scan 5 GB Files Without the Webhook Hassle
At attachmentAV, our goal is to make enterprise-grade malware protection as accessible as possible for developers. While our synchronous API has been the go-to for real-time scanning of smaller files, we know that modern applications often handle much larger data—up to several gigabytes.

Previously, scanning these large files asynchronously required setting up a callback URL (webhook) to receive results. Today, we are excited to announce a new capability that simplifies this workflow: Asynchronous Scan Polling.
The Challenge: Large Files and Timeouts
Synchronous API calls are great for speed, but they have limits. To ensure reliability, our synchronous scans are capped at 10 MB with a 60-second timeout. But what if you need to scan a 2 GB database export or a 5 GB media upload?
Our asynchronous engine has always supported files up to 5 GB, but it required you to maintain a publicly accessible endpoint to receive the results via a webhook. For CLI tools, internal scripts, or serverless functions, setting up a listener can be a significant overhead.
The Solution: Send, Poll, and Process
With the latest update to the attachmentAV Virus and Malware Scan API, you can now submit an async scan request and simply “poll” for the result using a unique scanId.
This means you get the best of both worlds:
- High Capacity: Scan files up to 5 GB.
- Simplified Infrastructure: No need to manage webhooks or public callback URLs.
How it works
Integrating the new polling mechanism is straightforward. Instead of providing a callbackUrl, you provide a traceId and poll the new GET /v1/scan/async/result API endpoint.
Here is a sample implementation using our JavaScript / TypeScript SDK:
import { AttachmentAVApi, Configuration, ResponseError } from '@attachmentav/virus-scan-sdk-ts';
import { randomUUID } from 'node:crypto';
import { exit } from 'node:process';
const config = new Configuration({
apiKey: '<API_KEY_PLACEHOLDER>'
});
const api = new AttachmentAVApi(config);
const traceId = randomUUID();
async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
await api.scanAsyncDownloadPost({
asyncDownloadScanRequest: {
downloadUrl: 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
traceId
}
});
console.log('Async download submitted. Start to poll for scan result...');
let i = 0;
while(true) {
try {
console.log('.');
const scanResult = await api.scanAsyncResultGet({
traceId
});
console.log('Async download scan result:', scanResult);
exit(0);
} catch (e: unknown) {
if (e instanceof ResponseError) {
if (e.response.status === 404) {
i++;
if (i < 10) {
await sleep(5000);
} else {
console.error('Async download scan result not found');
exit(1);
}
} else {
throw e;
}
} else {
throw e;
}
}
}
We also provide examples in:
Why Use Polling?
- CLI & Scripts: Perfect for automated migration scripts or maintenance tools that don’t run as a web service.
- Improved Security: No need to open firewall ports or expose endpoints to the internet just to receive scan results.
- Serverless Friendly: Easily manage long-running scan logic within a single execution flow (within timeout limits) or across step functions.
Powered by Sophos
The new polling feature is available today for our SaaS customers. As always, attachmentAV is powered by the Sophos engine and is fully ISO 27001 certified and GDPR compliant, ensuring your data remains secure and private.
Get Started
Ready to scan your large files?
- Update your SDK
- Read the documentation for more details.
Happy (and safe) coding!
Published on December 19, 2025 | Written by Michael