Scan for Malware with Python

Use AttachmentScanner to scan files and URLs for viruses and malware using the requests library.

Scan a URL

The simplest way to scan — pass a URL and get back a result:

import os
import requests

SCANNER_URL = os.environ["ATTACHMENT_SCANNER_URL"]
API_TOKEN = os.environ["ATTACHMENT_SCANNER_API_TOKEN"]
HEADERS = {"Authorization": f"Bearer {API_TOKEN}"}

response = requests.post(
    f"{SCANNER_URL}/v1.0/scans",
    headers=HEADERS,
    json={"url": "https://www.attachmentscanner.com/eicar.com"},
)

result = response.json()
print(result["status"])   # "found"
print(result["matches"])  # ["Eicar-Test-File-Signature"]

Scan a File

Upload a file directly from disk:

with open("/path/to/file.pdf", "rb") as f:
    response = requests.post(
        f"{SCANNER_URL}/v1.0/scans",
        headers=HEADERS,
        files={"file": ("file.pdf", f, "application/pdf")},
    )

result = response.json()
print(result["status"])  # "ok" if clean, "found" if malware detected

Async Scan with Callback

For large files or non-blocking workflows, use async: true with a callback URL. The API returns immediately with a pending status and POSTs the result to your callback when the scan completes:

# 1. Submit the scan
response = requests.post(
    f"{SCANNER_URL}/v1.0/scans",
    headers=HEADERS,
    json={
        "url": "https://example.com/large-file.zip",
        "async": True,
        "callback": "https://your-app.com/webhooks/scan-complete",
    },
)

scan = response.json()
scan_id = scan["id"]      # "a1b2c3d4-..."
print(scan["status"])     # "pending"
# 2. Handle the callback (Flask example)
@app.route("/webhooks/scan-complete", methods=["POST"])
def scan_callback():
    result = request.get_json()
    if result["status"] == "found":
        # quarantine or delete the file
        pass
    return jsonify({"received": True})

Or poll for results instead:

# Poll for results (alternative to callback)
result = requests.get(
    f"{SCANNER_URL}/v1.0/scans/{scan_id}",
    headers=HEADERS,
)

print(result.json()["status"])  # "ok", "found", "pending", etc.

Flask

A Flask app that accepts file uploads and scans them:

from flask import Flask, request, jsonify
import requests as http_requests

app = Flask(__name__)

@app.route("/scan/url", methods=["POST"])
def scan_url():
    body = request.get_json()
    response = http_requests.post(
        f"{SCANNER_URL}/v1.0/scans",
        headers=HEADERS,
        json={"url": body["url"]},
    )
    return jsonify(response.json())

@app.route("/scan/file", methods=["POST"])
def scan_file():
    file = request.files["file"]
    response = http_requests.post(
        f"{SCANNER_URL}/v1.0/scans",
        headers=HEADERS,
        files={"file": (file.filename, file.stream, file.content_type)},
    )
    return jsonify(response.json())

# Webhook callback handler
@app.route("/webhooks/scan-complete", methods=["POST"])
def scan_callback():
    result = request.get_json()
    if result["status"] == "found":
        print(f"Malware detected: {result['matches']}")
        # quarantine or delete the file
    elif result["status"] == "ok":
        # file is clean — move to final storage
        pass
    return jsonify({"received": True})

Django

import json
import requests as http_requests
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST

@csrf_exempt
@require_POST
def scan_url(request):
    body = json.loads(request.body)
    response = http_requests.post(
        f"{SCANNER_URL}/v1.0/scans",
        headers=HEADERS,
        json={"url": body["url"]},
    )
    return JsonResponse(response.json())

@csrf_exempt
@require_POST
def scan_file(request):
    uploaded = request.FILES["file"]
    response = http_requests.post(
        f"{SCANNER_URL}/v1.0/scans",
        headers=HEADERS,
        files={"file": (uploaded.name, uploaded, uploaded.content_type)},
    )
    return JsonResponse(response.json())

@csrf_exempt
@require_POST
def scan_callback(request):
    result = json.loads(request.body)
    if result["status"] == "found":
        # quarantine or delete the file
        pass
    elif result["status"] == "ok":
        # file is clean — move to final storage
        pass
    return JsonResponse({"received": True})

curl Equivalent

# Scan by URL
curl -X POST https://YOUR_SCANNER_URL/v1.0/scans \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.attachmentscanner.com/eicar.com"}'

# Scan by file upload
curl -X POST https://YOUR_SCANNER_URL/v1.0/scans \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "file=@/path/to/file.pdf"

# Async scan with callback
curl -X POST https://YOUR_SCANNER_URL/v1.0/scans \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/file.zip", "async": true, "callback": "https://your-app.com/webhooks/scan-complete"}'