Документация REST API
Сервис для проверки файлов на вирусы четырьмя независимыми движками. Поддерживается одиночное сканирование, пакетная обработка и кеширование результатов по SHA-256.
shield ClamAV
policy YARA Forge
verified_user Kaspersky
bug_report Dr.Web
info 1. Назначение и принцип работы
Сервис принимает загруженный файл и прогоняет его через четыре антивирусных движка одновременно. Если хотя бы один движок нашёл угрозу — файл считается заражённым (infected: true). Если все движки сказали «чисто» — файл безопасен (clean: true).
Результаты сканирования кешируются по SHA-256 хешу файла. При повторной загрузке того же файла ответ возвращается из кеша мгновенно.
Базовый URL
https://scan.fdw.ru
Движки
| Движок | Тип | Что детектит |
| ClamAV | Open-source AV | Известные семейства malware по сигнатурам |
| YARA Forge | Pattern-matching | ~10 000 курируемых правил, malware и эксплойты |
| Kaspersky KESL | Коммерческий AV | Полный движок Касперского + KSN облако |
| Dr.Web | Коммерческий AV | Движок Доктор Веб |
lock 2. Авторизация
Все запросы к API требуют HTTP-заголовок X-Api-Key с действующим ключом. Ключ выдаёт администратор.
X-Api-Key: ваш_ключ_здесь
Если ключ неверный, сервер вернёт 403 Forbidden.
api 3. Эндпоинты
POST /api/scan
Сканировать один файл. Тело запроса — multipart/form-data, поле file.
curl -X POST https://scan.fdw.ru/api/scan \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@/path/to/file.exe"
POST /api/scan-batch
Сканировать пачку файлов (до 20 за один запрос). Тело — multipart/form-data, поле files повторяется несколько раз.
curl -X POST https://scan.fdw.ru/api/scan-batch \
-H "X-Api-Key: YOUR_API_KEY" \
-F "files=@a.exe" -F "files=@b.pdf" -F "files=@c.doc"
Внутри сервер обрабатывает файлы последовательно. Для параллельной обработки делайте несколько запросов /api/scan с клиента (см. раздел 6).
GET /api/check/{sha256}
Проверить, есть ли результат сканирования для файла с заданным SHA-256 в кеше. Файл загружать не нужно.
curl https://scan.fdw.ru/api/check/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f
Если файл никогда не сканировался — {"found": false, "sha256": "..."}.
GET /api/stats
Общая статистика: сколько уникальных файлов в кеше, сколько из них заражённых, сколько всего запросов сканирования (с учётом cache-hit'ов).
curl https://scan.fdw.ru/api/stats
data_object 4. Формат ответа
Все ответы — JSON. Результат для одного файла:
{
"filename": "report.pdf",
"size": 13264,
"sha256": "3df79d34abbca99308e79cb94461c1893582604d68329a41fd4bec1885e6adb4",
"clean": true,
"infected": false,
"cached": false,
"results": {
"clamav": { "status": "clean", "threat": null },
"yara": { "status": "clean", "threat": null },
"kaspersky": { "status": "clean", "threat": null },
"drweb": { "status": "clean", "threat": null }
}
}
Поля верхнего уровня
| Поле | Тип | Описание |
filename | string | Имя файла из запроса |
size | integer | Размер файла в байтах |
sha256 | string | SHA-256 хеш файла (используется как ключ кеша) |
clean | boolean | true, если ни один движок не нашёл угрозу |
infected | boolean | true, если хотя бы один движок нашёл угрозу |
cached | boolean | true, если ответ взят из кеша (файл уже сканировался ранее) |
scan_date | string | Дата исходного сканирования (только для cached: true) |
scan_count | integer | Сколько раз файл проверяли (только для cached: true) |
results | object | Результаты по каждому движку (см. ниже) |
Статусы движков (поле status)
cleanДвижок не нашёл угрозу
infectedУгроза найдена, имя в поле threat
unavailableДвижок временно недоступен (нет лицензии, не запущен)
errorОшибка сканирования, подробности в error
Ответ при заражённом файле (пример с EICAR)
{
"filename": "test.com",
"size": 68,
"sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
"clean": false,
"infected": true,
"cached": false,
"results": {
"clamav": { "status": "infected", "threat": "Eicar-Test-Signature" },
"yara": { "status": "infected", "threat": "TRELLIX_ARC_Malw_Eicar" },
"kaspersky": { "status": "infected", "threat": "EICAR-Test-File" },
"drweb": { "status": "clean", "threat": null }
}
}
Ответ /api/scan-batch
{
"count": 3,
"infected_count": 1,
"results": [
{ /* объект как для /api/scan */ },
{ /* ... */ },
{ /* ... */ }
]
}
Привязка ответа к конкретному файлу запроса — по полю filename или sha256 внутри каждого элемента results[].
tune 5. Лимиты
| Параметр | Значение |
| Максимальный размер одного файла | 100 МБ |
Максимум файлов в одном /api/scan-batch | 20 |
| Таймаут одного скана (KESL и Dr.Web) | 120 секунд |
| Параллельных запросов на сервере | 2 worker'а (см. раздел 6) |
Превышение лимита файла — 413 Payload Too Large. Превышение лимита пакета — 400 Bad Request с описанием.
bolt 6. Параллельные запросы
Сервис запущен с двумя worker-процессами. Реальная производительность параллелизма зависит от размера файлов:
Лёгкие файлы (< 1 МБ)
До 4–5 параллельных запросов с минимальным замедлением. ClamAV+YARA реально параллелятся между worker'ами.
Тяжёлые файлы (5+ МБ)
Kaspersky и Dr.Web сериализуют свою часть. Параллелятся только ClamAV+YARA. Прирост ~10%.
Если нужно сканировать много файлов разом — используйте либо /api/scan-batch (до 20 файлов одним запросом), либо concurrent.futures на клиенте с несколькими параллельными запросами /api/scan.
code 7. Примеры на Python
Один файл
import requests
resp = requests.post(
"https://scan.fdw.ru/api/scan",
headers={"X-Api-Key": "YOUR_API_KEY"},
files={"file": open("file.exe", "rb")},
timeout=180,
)
data = resp.json()
print(f"SHA-256: {data['sha256']}")
print(f"Cached: {data['cached']}")
print("Clean" if data["clean"] else "INFECTED!")
Пачка файлов через batch
import requests
files = [("files", open(p, "rb")) for p in ["a.exe", "b.pdf", "c.doc"]]
resp = requests.post(
"https://scan.fdw.ru/api/scan-batch",
headers={"X-Api-Key": "YOUR_API_KEY"},
files=files,
timeout=600,
)
data = resp.json()
print(f"{data['infected_count']}/{data['count']} infected")
for r in data["results"]:
print(r["filename"], r["sha256"], "INFECTED" if r.get("infected") else "ok")
Несколько параллельных запросов с клиента
import requests
from concurrent.futures import ThreadPoolExecutor
def scan_one(path):
with open(path, "rb") as f:
return requests.post(
"https://scan.fdw.ru/api/scan",
headers={"X-Api-Key": "YOUR_API_KEY"},
files={"file": f},
timeout=180,
).json()
with ThreadPoolExecutor(max_workers=4) as ex:
for r in ex.map(scan_one, ["a.exe", "b.pdf", "c.doc"]):
print(r["filename"], "INFECTED" if r["infected"] else "ok")
Проверка по хешу без загрузки файла
import hashlib, requests
sha = hashlib.sha256(open("file.exe","rb").read()).hexdigest()
r = requests.get(f"https://scan.fdw.ru/api/check/{sha}").json()
if r["found"]:
print("Уже сканировали:", "INFECTED" if r["infected"] else "clean")
else:
print("Файла нет в кеше, нужен полноценный /api/scan")
help 8. Коды ответа
| Код | Описание |
200 OK | Запрос выполнен, файл просканирован, см. JSON |
400 Bad Request | Неверный запрос (например, > 20 файлов в batch) |
403 Forbidden | Неверный X-Api-Key |
413 Payload Too Large | Файл больше 100 МБ |
422 Unprocessable Entity | Неверная структура multipart-формы |
500 / 504 | Внутренняя ошибка / таймаут одного из движков (попробуйте позже) |