Using virustotal

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.

Installation

From CRAN:

install.packages("virustotal")

Or the development version from GitHub, with pak:

pak::pak("themains/virustotal")

Load the library

library(virustotal)

Authentication

  1. Get your free API key from VirusTotal
  2. Set it once per session:
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.

Core Functions

File Analysis

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

URL Analysis

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 Intelligence

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 Address Intelligence

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

Rate Limiting, Retries and Timeouts

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
)

Error Handling

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.