The virustotal package provides access to the VirusTotal API v3, allowing you to scan files and URLs for malware, get domain and IP intelligence, and retrieve comprehensive threat analysis reports.
From CRAN:
install.packages("virustotal")
Or the development version from GitHub, with pak:
pak::pak("themains/virustotal")
library(virustotal)
set_key("your_api_key_here")
Or set the VIRUSTOTAL_API_KEY environment variable (for
example in ~/.Renviron) and skip set_key()
entirely. The historical VirustotalToken variable is still
honored.
Scan a file for malware:
result <- scan_file("path/to/suspicious_file.exe")
analysis_id <- result$data$id
Get file analysis report:
report <- file_report("99017f6eebbac24f351415dd410d522d")
report
## VirusTotal API Response
## ======================
##
## Type: File Report
## ID: 99017f6eebbac24f351415dd410d522d
## Resource Type: file
##
## Detection Summary:
## Malicious: 61
## Suspicious: 0
## Undetected: 4
## Harmless: 0
The raw response stays a list underneath:
scan_results <- report$data$attributes$last_analysis_results
detections <- sum(sapply(scan_results, function(x) x$category == "malicious"))
Request file rescan:
rescan_result <- rescan_file("99017f6eebbac24f351415dd410d522d")
new_analysis_id <- rescan_result$data$id
Scan a URL:
url_result <- scan_url("http://www.example.com")
analysis_id <- url_result$data$id
Get URL analysis report:
report <- url_report("http://www.google.com")
scan_results <- report$data$attributes$last_analysis_results
domain_info <- domain_report("google.com")
categories <- domain_info$data$attributes$categories
whois_data <- domain_info$data$attributes$whois
dns_records <- domain_info$data$attributes$last_dns_records
ip_info <- ip_report("8.8.8.8")
country <- ip_info$data$attributes$country
asn <- ip_info$data$attributes$asn
network <- ip_info$data$attributes$network
The package paces itself to the public API’s allowance (4 requests
per minute) and retries transient failures (HTTP 429 and 503), honoring
the server’s Retry-After header. Four options control
this:
options(
virustotal.requests_per_minute = 1000, # premium keys can go faster
virustotal.max_tries = 3, # attempts per request
virustotal.timeout = 60, # seconds
virustotal.throttle = TRUE # FALSE disables client-side pacing
)
API failures are typed conditions, so specific failures can be handled without string-matching messages:
tryCatch(
file_report("0000000000000000000000000000000000000000"),
virustotal_rate_limit_error = function(e) {
message("Out of quota; retry after ", e$retry_after, "s")
},
virustotal_auth_error = function(e) message("Check the API key"),
virustotal_error = function(e) message("VT error: ", conditionMessage(e))
)
The classes are virustotal_auth_error,
virustotal_rate_limit_error (with a
retry_after field),
virustotal_validation_error (bad input, thrown before any
network traffic), and their parent virustotal_error.