Scan for Malware with PHP

Use AttachmentScanner to scan files and URLs for viruses and malware using GuzzleHttp.

Scan a URL

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

<?php
require __DIR__ . '/vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client([
    'base_uri' => getenv('ATTACHMENT_SCANNER_URL'),
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('ATTACHMENT_SCANNER_API_TOKEN'),
    ],
]);

$response = $client->post('/v1.0/scans', [
    'json' => ['url' => 'https://www.attachmentscanner.com/eicar.com'],
]);

$result = json_decode($response->getBody(), true);
echo $result['status'];  // "found"
print_r($result['matches']); // ["Eicar-Test-File-Signature"]

Scan a File

Upload a file directly from disk:

<?php
$response = $client->post('/v1.0/scans', [
    'multipart' => [
        [
            'name' => 'file',
            'contents' => fopen('/path/to/file.pdf', 'r'),
            'filename' => 'file.pdf',
        ],
    ],
]);

$result = json_decode($response->getBody(), true);
echo $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:

<?php
// 1. Submit the scan
$response = $client->post('/v1.0/scans', [
    'json' => [
        'url' => 'https://example.com/large-file.zip',
        'async' => true,
        'callback' => 'https://your-app.com/webhooks/scan-complete',
    ],
]);

$scan = json_decode($response->getBody(), true);
echo $scan['id'];     // "a1b2c3d4-..."
echo $scan['status']; // "pending"
<?php
// 2. Handle the callback
$result = json_decode(file_get_contents('php://input'), true);

if ($result['status'] === 'found') {
    // quarantine or delete the file
}

echo json_encode(['received' => true]);

Or poll for results instead:

<?php
// Poll for results (alternative to callback)
$response = $client->get('/v1.0/scans/' . $scan['id']);
$result = json_decode($response->getBody(), true);
echo $result['status']; // "ok", "found", "pending", etc.

Laravel

A Laravel controller that accepts file uploads and scans them:

<?php

namespace App\Http\Controllers;

use GuzzleHttp\Client;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

class ScanController extends Controller
{
    private Client $client;

    public function __construct()
    {
        $this->client = new Client([
            'base_uri' => env('ATTACHMENT_SCANNER_URL'),
            'headers' => [
                'Authorization' => 'Bearer ' . env('ATTACHMENT_SCANNER_API_TOKEN'),
            ],
        ]);
    }

    public function scanUrl(Request $request): JsonResponse
    {
        $response = $this->client->post('/v1.0/scans', [
            'json' => ['url' => $request->input('url')],
        ]);

        return response()->json(
            json_decode($response->getBody(), true)
        );
    }

    public function scanFile(Request $request): JsonResponse
    {
        $file = $request->file('file');

        $response = $this->client->post('/v1.0/scans', [
            'multipart' => [
                [
                    'name' => 'file',
                    'contents' => fopen($file->getPathname(), 'r'),
                    'filename' => $file->getClientOriginalName(),
                ],
            ],
        ]);

        return response()->json(
            json_decode($response->getBody(), true)
        );
    }

    // Webhook callback handler
    public function scanCallback(Request $request): JsonResponse
    {
        $result = $request->all();

        if ($result['status'] === 'found') {
            // quarantine or delete the file
        } elseif ($result['status'] === 'ok') {
            // file is clean — move to final storage
        }

        return response()->json(['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"}'