VirusTotal API v3 mengadopsi standar spesifikasi JSON:API secara penuh. Setiap respons sukses (status kode HTTP 200 OK) dibungkus dalam objek utama bernama data, yang memuat empat kunci hierarki primer: id (identifier objek), type (tipe entitas seperti file, url, domain, ip_address, atau analysis), links (tautan sumber daya), dan attributes (kontainer utama metadata hasil analisis keamanan).
Kunci paling krusial bagi analis SOC dan developer terletak pada attributes.last_analysis_stats yang menyediakan kalkulasi agregat deteksi vendor, serta attributes.last_analysis_results yang merinci vonis granular dari tiap-tiap mesin antivirus pihak ketiga.
Struktur Skema JSON VirusTotal API v3 (Contoh File Report)
Berikut adalah payload JSON nyata hasil kueri endpoint GET /api/v3/files/{hash} yang telah divalidasi sesuai spesifikasi produksi VirusTotal API v3:
{
"data": {
"id": "44d88612fea8a8f36de82e1278abb02f",
"type": "file",
"links": {
"self": "https://www.virustotal.com/api/v3/files/44d88612fea8a8f36de82e1278abb02f"
},
"attributes": {
"meaningful_name": "malware_sample.exe",
"type_description": "Win32 EXE",
"size": 68608,
"md5": "44d88612fea8a8f36de82e1278abb02f",
"sha1": "9292816912ec924513686fa3a48e2da3a2334ef5",
"sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
"reputation": -42,
"last_analysis_date": 1711929600,
"times_submitted": 14,
"last_analysis_stats": {
"malicious": 58,
"suspicious": 1,
"undetected": 12,
"harmless": 0,
"timeout": 0,
"confirmed-timeout": 0,
"failure": 0,
"type-unsupported": 2
},
"last_analysis_results": {
"Kaspersky": {
"category": "malicious",
"result": "Trojan.Win32.Swizzor",
"method": "blacklist",
"engine_name": "Kaspersky",
"engine_version": "21.0.1.45",
"engine_update": "20260330"
},
"Microsoft": {
"category": "malicious",
"result": "Trojan:Win32/Wacatac.B!ml",
"method": "blacklist",
"engine_name": "Microsoft",
"engine_version": "1.1.24030.1",
"engine_update": "20260330"
},
"Google": {
"category": "undetected",
"result": null,
"method": "blacklist",
"engine_name": "Google Safe Browsing",
"engine_version": "1.0",
"engine_update": "20260330"
}
}
}
}
}Hierarki dan Definisi Kunci Field JSON API v3
Memahami hierarki field sangat penting agar pipeline parser log otomatis di SIEM atau backend tidak mengalami galat KeyError atau membaca field yang salah interpretasi.
| Path JSON | Tipe Data | Fungsi dan Keterangan |
|---|---|---|
data.id | String | Identifier unik objek: MD5/SHA-256 untuk file, ID sandi base64 untuk URL, domain murni, atau alamat IPv4/IPv6. |
data.type | String | Menentukan schema parser: file, url, domain, ip_address, atau analysis. |
data.attributes.last_analysis_stats | Object | Kalkulator metrik total: merangkum jumlah engine pada kategori malicious, suspicious, undetected, dan harmless. |
data.attributes.last_analysis_results | Object (Map) | Daftar objek asosiatif berindeks nama vendor (mis. Kaspersky, CrowdStrike, Sophos). |
last_analysis_results.{vendor}.category | String | Status vonis vendor: bernilai malicious, suspicious, undetected, harmless, atau type-unsupported. |
last_analysis_results.{vendor}.result | String | Null | Label deteksi ancaman/keluarga malware (contoh: Ransom:Win32/WannaCrypt). Bernilai null jika bersih/undetected. |
data.attributes.reputation | Integer | Skor reputasi crowdsourced dari komunitas VirusTotal (bisa bernilai negatif untuk sampel berbahaya). |
data.attributes.last_analysis_date | Integer (Epoch) | Timestamp waktu pemindaian terakhir dalam format detik Unix. |
Format Payload URL Scan vs Analysis Queue Object
Saat mengirimkan URL baru atau file biner ke VirusTotal via HTTP POST, API tidak langsung mengembalikan hasil pemindaian akhir, melainkan objek tipe analysis yang berisi ID token antrean:
{
"data": {
"type": "analysis",
"id": "dTFhMmM4MjY5NmIyODJhNGRmZjQ3MTAyMmFiNmExNzU6MTcxMTkyOTYwMA==",
"links": {
"self": "https://www.virustotal.com/api/v3/analyses/dTFhMmM4MjY5NmIyODJhNGRmZjQ3MTAyMmFiNmExNzU6MTcxMTkyOTYwMA=="
}
}
}Status antrean tersebut harus dipantau secara polling pada endpoint GET /api/v3/analyses/{id} hingga field attributes.status beralih dari queued menjadi completed sebelum mengekstrak field stats.
Skrip Ekstraksi Data: Parsing JSON VirusTotal dengan Python
Gunakan implementasi Python berikut untuk membaca payload JSON VirusTotal secara aman tanpa memicu crash akibat key yang hilang (menggunakan pendekatan dict.get() defensif):
import requests
def parse_virustotal_report(resource_hash, api_key):
url = f"https://www.virustotal.com/api/v3/files/{resource_hash}"
headers = {
"x-apikey": api_key,
"Accept": "application/json"
}
response = requests.get(url, headers=headers)
if response.status_code != 200:
return {"error": f"HTTP {response.status_code}: {response.text}"}
payload = response.json()
attributes = payload.get("data", {}).get("attributes", {})
stats = attributes.get("last_analysis_stats", {})
results = attributes.get("last_analysis_results", {})
# Ambil vendor yang mendeteksi malicious secara spesifik
flagged_engines = []
for engine, details in results.items():
if details.get("category") == "malicious":
flagged_engines.append({
"engine": engine,
"threat_label": details.get("result")
})
return {
"sha256": attributes.get("sha256"),
"file_size": attributes.get("size"),
"positives": stats.get("malicious", 0),
"total_engines": sum(stats.values()),
"reputation": attributes.get("reputation", 0),
"detections": flagged_engines
}
# Eksekusi
# report = parse_virustotal_report("275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f", "YOUR_API_KEY")
# print(report)Format Respons Galat (Error Schema)
Jika request gagal karena limitasi kuota (rate limit 4 requests/menit untuk API publik) atau kesalahan autentikasi API key, VirusTotal mengembalikan payload galat berskema berikut:
{
"error": {
"code": "QuotaExceededError",
"message": "Quota exceeded for request: 4 per minute, you sent 5"
}
}Kode error umum yang wajib ditangani di layer aplikasi meliputi NotFoundError (HTTP 404 jika hash belum pernah terdaftar), AuthenticationRequiredError (HTTP 401 header x-apikey tidak valid), dan QuotaExceededError (HTTP 429 backoff throttling).