× Cookies are disabled! This site requires cookies to be enabled to work properly

VirusTotal's Public API lets you upload and scan files, submit and scan URLs, access finished scan reports and make automatic comments on URLs and samples without the need of using the HTML website interface. In other words, it allows you to build simple scripts to access the information generated by VirusTotal.

The chosen format for the API is HTTP POST requests with JSON object responses and it is limited to at most 4 requests of any nature in any given 1 minute time frame. If you run a honeyclient, honeypot or any other automation that is going to provide resources to VirusTotal and not only retrieve reports you are entitled to a higher request rate quota, ask for it at and you will receive special privileges when performing the calls to the API. Note that you will only have a higher request rate quota when asking for files or URLs that you previously sent to VirusTotal.

In this second version we have improved the response format so as to ease the task of retrieving results, we have also introduced batch requests, you may now ask for several items with a sole API call (as long as you cohere with the request rate limit).

The public API is a free service, available for any website or application that is free to consumers. The API must not be used in commercial products or services, it can not be used as a substitute for antivirus products and it can not be integrated in any project that may harm the antivirus industry directly or indirectly. Noncompliance of these terms will result in immediate permanent ban of the infractor individual or organization. Please see the terms of service for more information.

Contents

Audience
Getting started
Response basics
Sending and scanning files
Rescanning already submitted files
Retrieving file scan reports
Sending and scanning URLs
Retrieving URL scan reports
Retrieving IP address reports (includes Passive DNS)
Retrieving domain reports (includes Passive DNS)
Making comments on files and URLs
Scripts to interact with the public API

Audience

This document is intended for programmers who want to write client applications that can interact with VirusTotal using JSON and HTTP.

This document assumes that you understand general networking and programming ideas. Even though code examples are built using python, any programming language of your choice can be used to interact with this API.

Getting started

The process could not be easier. Sign up to VirusTotal Community. Once you have a valid VirusTotal Community account, you will find your personal API key in your Community profile. This key is all you need to use VirusTotal's API.

Response basics

The API response format is a JSON object containing at least the following two properties:

  • response_code: if the item you searched for was not present in VirusTotal's dataset this result will be 0. If the requested item is still queued for analysis it will be -2. If the item was indeed present and it could be retrieved it will be 1. Any other case is detailed in the following sections.
  • verbose_msg: provides verbose information regarding the response_code property.

Whenever you exceed the public API request rate limit a 204 HTTP status code is returned. If you try to perform calls to functions for which you do not have the required privileges an HTTP Error 403 Forbidden is raised.

Sending and scanning files

The VirusTotal API allows you to send files. Before performing your submissions we encourage you to retrieve the latest report on the files, if it is recent enough you might want to save time and bandwidth by making use of it. File size limit is 32MB. If you have a need to scan larger files, please contact us, and tell us your use case.

In order to send a file you must perform an HTTP POST request to the following URL:

https://www.virustotal.com/vtapi/v2/file/scan

This API call expects multipart/form-data parameters, the string part of the the call should have the following parameter:

  • apikey: your API key.

The file part of the call should contain the name of the submitted file and the file itself. We strongly encourage you to send the file with the name with which it was found in the wild since this is very rich metadata for the VirusTotal database.

Summing up, the API acts like a form with a file input field named file.

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-'}
files = {'file': ('myfile.exe', open('myfile.exe', 'rb'))}
response = requests.post('https://www.virustotal.com/vtapi/v2/file/scan', files=files, params=params)
json_response = response.json()
        
curl -v -F 'file=@/path/to/file' -F \
  apikey=${VT_API_KEY} https://www.virustotal.com/vtapi/v2/file/scan
        

$file_name_with_full_path = realpath('/path/to/file');
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';
$cfile = curl_file_create($file_name_with_full_path);

$post = array('apikey' => $api_key,'file'=> $cfile);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/file/scan');
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); // please compress data
curl_setopt($ch, CURLOPT_USERAGENT, "gzip, My php curl client");
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,True);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result=curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
  $js = json_decode($result, true);
  print_r($js);
} else {  // Error occured
  print($result);
}
curl_close ($ch);

        

Example response:

{
  'permalink': 'https://www.virustotal.com/file/d140c...244ef892e5/analysis/1359112395/',
  'resource': u'd140c244ef892e59c7f68bd0c6f74bb711032563e2a12fa9dda5b760daecd556',
  'response_code': 1,
  'scan_id': 'd140c244ef892e59c7f68bd0c6f74bb711032563e2a12fa9dda5b760daecd556-1359112395',
  'verbose_msg': 'Scan request successfully queued, come back later for the report',
  'sha256': 'd140c244ef892e59c7f68bd0c6f74bb711032563e2a12fa9dda5b760daecd556'
}

The scan_id field of the JSON object lets us query the report later making use of the file report retrieving API. Keep in mind that files sent using the API have the lowest scanning priority, depending on VirusTotal's load, it may take several hours before the file is scanned, so query the report at regular intervals until the result shows up and do not keep sending the file repeatedly.

Rescanning already submitted files

The call allows you to rescan files in VirusTotal's file store without having to resubmit them, thus saving bandwidth.

The VirusTotal public API allows you to rescan files that you or other users already sent in the past and, hence, are already present in our file store. Before requesting a rescan we encourage you to retrieve the latest report on the files, if it is recent enough you might want to save time and bandwidth by making use of it.

In order to request a rescan you must perform an HTTP POST request to the following URL:

https://www.virustotal.com/vtapi/v2/file/rescan

This API call expects the following HTTP POST parameters:

  • resource: a md5/sha1/sha256 hash. You can also specify a CSV list made up of a combination of any of the three allowed hashes (up to 25 items), this allows you to perform a batch request with one single call. Note that the file must already be present in our file store.
  • apikey: your API key.

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'resource': '7657fcb7d772448a6d8504e4b20168b8'}
headers = {
  "Accept-Encoding": "gzip, deflate",
  "User-Agent" : "gzip,  My Python requests library example client or username"
  }
response = requests.post('https://www.virustotal.com/vtapi/v2/file/rescan',
 params=params)
json_response = response.json()
        
curl -v --request POST \
  --url 'https://www.virustotal.com/vtapi/v2/file/rescan' \
  -d apikey=${VT_API_KEY} \
  -d 'resource=7657fcb7d772448a6d8504e4b20168b8'
        
$post = array('apikey' => 'YOUR_API_KEY','resource'=>'99017f6eebbac24f351415dd410d522d');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/file/rescan');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); // please compress data
curl_setopt($ch, CURLOPT_USERAGENT, "gzip, My php curl client");
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
  $js = json_decode($result, true);
  print_r($js);
} else {  // Error occured
  print($result);
}
curl_close ($ch);

        

Example response:

{
  'response_code': 1,
  'scan_id': '54bc950d46a0d1aa72048a17c8275743209e6c17bdacfc4cb9601c9ce3ec9a71-1390472785'
  'permalink': 'https://www.virustotal.com/file/__sha256hash__/analysis/1390472785/',
  'sha256': '54bc950d46a0d1aa72048a17c8275743209e6c17bdacfc4cb9601c9ce3ec9a71',
  'resource': '7657fcb7d772448a6d8504e4b20168b8',
}

The response_code field of the individual responses will be 1 if the file corresponding to the given hash was successfully queued for rescanning. If the file was not present in our file store this code will be 0. In the event of some unexpected error the code will be fixed to -1.

The scan_id field of the individual responses lets us query the report later making use of the file report retrieving API. Keep in mind that files sent using the API have the lowest scanning priority, depending on VirusTotal's load, it may take several hours before the file is scanned, so query the report at regular intervals until the result shows up and do not keep sending the file rescan requests once and over again.

Retrieving file scan reports

In order to retrieve a scan report on a given file you must perform an HTTP POST request to the following URL:

https://www.virustotal.com/vtapi/v2/file/report

With the following two HTTP POST parameters:

  • resource: a md5/sha1/sha256 hash will retrieve the most recent report on a given sample. You may also specify a scan_id (sha256-timestamp as returned by the file upload API) to access a specific report. You can also specify a CSV list made up of a combination of hashes and scan_ids (up to 4 items with the standard request rate), this allows you to perform a batch request with one single call.
  • apikey: your API key.

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'resource': '7657fcb7d772448a6d8504e4b20168b8'}
headers = {
  "Accept-Encoding": "gzip, deflate",
  "User-Agent" : "gzip,  My Python requests library example client or username"
  }
response = requests.get('https://www.virustotal.com/vtapi/v2/file/report',
  params=params, headers=headers)
json_response = response.json()
        
curl -v --request POST \
  --url 'https://www.virustotal.com/vtapi/v2/file/report' \
  -d apikey=${VT_API_KEY} \
  -d 'resource=7657fcb7d772448a6d8504e4b20168b8'
        
$post = array('apikey' => 'YOUR_API_KEY','resource'=>'99017f6eebbac24f351415dd410d522d');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/file/report');
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); // please compress data
curl_setopt($ch, CURLOPT_USERAGENT, "gzip, My php curl client");
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
  $js = json_decode($result, true);
  print_r($js);
} else {  // Error occured
  print($result);
}
curl_close ($ch);

        

Example response:

{
 'response_code': 1,
 'verbose_msg': 'Scan finished, scan information embedded in this object',
 'resource': '99017f6eebbac24f351415dd410d522d',
 'scan_id': '52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c-1273894724',
 'md5': '99017f6eebbac24f351415dd410d522d',
 'sha1': '4d1740485713a2ab3a4f5822a01f645fe8387f92',
 'sha256': '52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c',
 'scan_date': '2010-05-15 03:38:44',
 'positives': 40,
 'total': 40,
 'scans': {
    'nProtect': {'detected': true, 'version': '2010-05-14.01', 'result': 'Trojan.Generic.3611249', 'update': '20100514'},
    'CAT-QuickHeal': {'detected': true, 'version': '10.00', 'result': 'Trojan.VB.acgy', 'update': '20100514'},
    'McAfee': {'detected': true, 'version': '5.400.0.1158', 'result': 'Generic.dx!rkx', 'update': '20100515'},
    'TheHacker': {'detected': true, 'version': '6.5.2.0.280', 'result': 'Trojan/VB.gen', 'update': '20100514'},
    .
    .
    .
    'VirusBuster': {'detected': true, 'version': '5.0.27.0', 'result': 'Trojan.VB.JFDE', 'update': '20100514'},
    'NOD32': {'detected': true, 'version': '5115', 'result': 'a variant of Win32/Qhost.NTY', 'update': '20100514'},
    'F-Prot': {'detected': false, 'version': '4.5.1.85', 'result': null, 'update': '20100514'},
    'Symantec': {'detected': true, 'version': '20101.1.0.89', 'result': 'Trojan.KillAV', 'update': '20100515'},
    'Norman': {'detected': true, 'version': '6.04.12', 'result': 'W32/Smalltroj.YFHZ', 'update': '20100514'},
    'TrendMicro-HouseCall': {'detected': true, 'version': '9.120.0.1004', 'result': 'TROJ_VB.JVJ', 'update': '20100515'},
    'Avast': {'detected': true, 'version': '4.8.1351.0', 'result': 'Win32:Malware-gen', 'update': '20100514'},
    'eSafe': {'detected': true, 'version': '7.0.17.0', 'result': 'Win32.TRVB.Acgy', 'update': '20100513'}
  },
 'permalink': 'https://www.virustotal.com/file/52d3df0ed60c46f336c131bf2ca454f73bafdc4b04dfa2aea80746f5ba9e6d1c/analysis/1273894724/'
}

If you are interested in the additional information included in web reports (file analysis tools like Portable Executable properties, ExifTool information, file signing information, etc.) then you should consider the private API.

Sending and scanning URLs

URLs can also be submitted for scanning. Once again, before performing your submission we encourage you to retrieve the latest report on the URL, if it is recent enough you might want to save time and bandwidth by making use of it.

To submit a URL you must perform an HTTP POST request to the following URL:

https://www.virustotal.com/vtapi/v2/url/scan

This API call expects the following HTTP POST parameters:

  • url: The URL that should be scanned. This parameter accepts a list of URLs (up to 4 with the standard request rate) so as to perform a batch scanning request with one single call. The URLs must be separated by a new line character.
  • apikey: your API key.

Some python code will hopefully illustrate better how this is done:

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'url':'http://www.virustotal.com'}
response = requests.post('https://www.virustotal.com/vtapi/v2/url/scan', data=params)
json_response = response.json()
        
curl -v --request POST \
  --url 'https://www.virustotal.com/vtapi/v2/url/scan' \
  -d apikey=${VT_API_KEY} \
  -d 'url=https://www.google.com/'
        
$virustotal_api_key = 'YOUR_API_KEY';
$scan_url = 'https://www.google.com/';

$post = array('apikey' => $virustotal_api_key,'url'=> $scan_url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/url/scan');
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,True);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result=curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
  $js = json_decode($result, true);
  print_r($js);
} else {  // Error occured
  print($result);
}
curl_close ($ch);

        

Example response:

{
  'response_code': 1,
  'verbose_msg': 'Scan request successfully queued, come back later for the report',
  'scan_id': '1db0ad7dbcec0676710ea0eaacd35d5e471d3e11944d53bcbd31f0cbd11bce31-1320752364',
  'scan_date': '2015-11-08 11:39:24',
  'url': 'http://www.virustotal.com/',
  'permalink': 'http://www.virustotal.com/url/1db0ad7dbcec0676710ea0eaacd35d5e471d3e11944d53bcbd31f0cbd11bce31/analysis/1320752364/'
}

The scan_id parameter of the JSON object can then be used to query for the scan report making use of the URL scan report retrieving API described in the next section. Keep in mind that URLs sent using the API have the lowest scanning priority, depending on VirusTotal's load, it may take several hours before the URL is scanned, so query the report at regular intervals until the result shows up and do not keep submitting the URL once and over again.

Retrieving URL scan reports

In order to retrieve a scan report on a given URL you must perform an HTTP POST request to the following URL:

http://www.virustotal.com/vtapi/v2/url/report

With the following HTTP POST parameters:

  • resource: a URL will retrieve the most recent report on the given URL. You may also specify a scan_id (sha256-timestamp as returned by the URL submission API) to access a specific report. At the same time, you can specify a CSV list made up of a combination of hashes and scan_ids so as to perform a batch request with one single call (up to 4 resources per call with the standard request rate). When sending multiples, the scan_ids or URLs must be separated by a new line character.
  • scan (optional): this is an optional parameter that when set to "1" will automatically submit the URL for analysis if no report is found for it in VirusTotal's database. In this case the result will contain a scan_id field that can be used to query the analysis report later on.
  • apikey: your API key.

Some python code will hopefully illustrate better how this is done:

Example Code:

import requests
headers = {
  "Accept-Encoding": "gzip, deflate",
  "User-Agent" : "gzip,  My Python requests library example client or username"
  }
params = {'apikey': '-YOUR API KEY HERE-', 'resource':'http://www.virustotal.com'}
response = requests.post('https://www.virustotal.com/vtapi/v2/url/report',
  params=params, headers=headers)
json_response = response.json()

        
curl -v --request POST \
  --url 'https://www.virustotal.com/vtapi/v2/url/report' \
  -d apikey=${VT_API_KEY} \
  -d 'resource=http://www.virustotal.com/'
        
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';
$scan_url = 'https://www.google.com/';

$post = array('apikey' => $api_key,'resource'=> $scan_url);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.virustotal.com/vtapi/v2/url/report');
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_VERBOSE, 1); // remove this if your not debugging
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate'); // please compress data
curl_setopt($ch, CURLOPT_USERAGENT, "gzip, My php curl client");
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,True);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$result=curl_exec ($ch);
$status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
print("status = $status_code\n");
if ($status_code == 200) { // OK
  $js = json_decode($result, true);
  print_r($js);
} else {  // Error occured
  print($result);
}
curl_close ($ch);
        

Example response:

{
  'response_code': 1,
  'verbose_msg': 'Scan finished, scan information embedded in this object',
  'scan_id': '1db0ad7dbcec0676710ea0eaacd35d5e471d3e11944d53bcbd31f0cbd11bce31-1390467782',
  'permalink': 'https://www.virustotal.com/url/__urlsha256__/analysis/1390467782/',
  'url': 'http://www.virustotal.com/',
  'scan_date': '2014-01-23 09:03:02',
  'filescan_id': None,
  'positives': 0,
  'total': 51,
  'scans': {
      'CLEAN MX': {'detected': False, 'result': 'clean site'},
      'MalwarePatrol': {'detected': False, 'result': 'clean site'}
      [... continues ...]
  }
}
    

Note that the second call makes use of the batch request feature. The results for each resource are JSON objects with several properties describing the scan output and metadata. If you are interested in the additional information included in web reports (web response headers, website content category according to different tools, threat description, etc.) you should consider the private API.

Retrieving IP address reports

In order to retrieve a report on a given IP address (including the information recorded by VirusTotal's Passive DNS infrastructure) you must perform an HTTP GET request to the following URL:

http://www.virustotal.com/vtapi/v2/ip-address/report

With the following HTTP GET parameters:

  • ip: a valid IPv4 address in dotted quad notation, for the time being only IPv4 addresses are supported.
  • apikey: your API key.

Some python code will hopefully illustrate better how this is done:

>>> import json
>>> import urllib
>>> url = 'https://www.virustotal.com/vtapi/v2/ip-address/report'
>>> parameters = {'ip': '90.156.201.27', 'apikey': '-- YOUR API KEY --'}
>>> response = urllib.urlopen('%s?%s' % (url, urllib.urlencode(parameters))).read()
>>> response_dict = json.loads(response)
>>> print response_dict
{u'response_code': 1,
 u'verbose_msg': u'IP address found in dataset',
 u'resolutions': [
    {u'last_resolved': u'2013-04-08 00:00:00', u'hostname': u'027.ru'},
    {u'last_resolved': u'2013-04-08 00:00:00', u'hostname': u'auto.rema-tiptop.ru'},
    {u'last_resolved': u'2013-04-08 00:00:00', u'hostname': u'catalog24de.ru'},
    {u'last_resolved': u'2013-04-08 00:00:00', u'hostname': u'club.velhod.ru'},
    {u'last_resolved': u'2013-04-08 00:00:00', u'hostname': u'danilova.pro'},
    ... continues ...
  ],
 u'detected_urls': [
    {"url": "http://027.ru/", "positives": 2, "total": 37, "scan_date": "2013-04-07 07:18:09"},
    ... continues ...
 ]}

Please note that only 1000 different domain name mappings will be returned at most.

As you may have noticed, not only does the report include the passive DNS data on the IP address, but also the latest URLs detected by at least one URL scanner and hosted at such IP address. This additional information may increase with time, including new notions such as the latest malware samples that were seen communicating with the given IP address, malware specimens that were downloaded from such IP address, etc.

If VirusTotal has absolutely no information regarding the IP address under consideration, the JSON's response code will be 0, -1 if the submitted IP address is invalid.

Retrieving domain reports

In order to retrieve a report on a given domain (including the information recorded by VirusTotal's Passive DNS infrastructure) you must perform an HTTP GET request to the following URL:

http://www.virustotal.com/vtapi/v2/domain/report

With the following HTTP GET parameters:

  • domain: a domain name.
  • apikey: your API key.

Some python code will hopefully illustrate better how this is done:

>>> import json
>>> import urllib
>>> url = 'https://www.virustotal.com/vtapi/v2/domain/report'
>>> parameters = {'domain': '027.ru', 'apikey': '-- YOUR API KEY --'}
>>> response = urllib.urlopen('%s?%s' % (url, urllib.urlencode(parameters))).read()
>>> response_dict = json.loads(response)
>>> print response_dict
{"response_code": 1,
 "verbose_msg": "Domain found in dataset",
 "resolutions": [
    {"last_resolved": "2013-04-05 00:00:00", "ip_address": "90.156.201.11"},
    {"last_resolved": "2013-04-07 00:00:00", "ip_address": "90.156.201.14"},
    {"last_resolved": "2013-04-08 00:00:00", "ip_address": "90.156.201.27"},
    {"last_resolved": "2013-04-07 00:00:00", "ip_address": "90.156.201.71"},
    ... continues ...
  ],
 "detected_urls": [
    {"url": "http://027.ru/", "positives": 2, "total": 37, "scan_date": "2013-04-07 07:18:09"},
    ... continues ...
  ]}

Please note that only 1000 different IP address resolutions will be returned at most.

As you may have noticed, not only does the report include the passive DNS data on the domain, but also the latest URLs detected by at least one URL scanner and hosted at such domain. This additional information may increase with time, including new notions such as the latest malware samples that were seen communicating with the given domain, malware specimens that were downloaded from such domain, etc.

If VirusTotal has absolutely no information regarding the domain under consideration, the JSON's response code will be 0, -1 if the submitted domain is invalid.

Make comments on files and URLs

The initial idea of VirusTotal Community was that users should be able to make comments on files and URLs, the comments may be malware analyses, false positive flags, disinfection instructions, etc.

Imagine you have some automatic setup that can produce interesting results related to a given sample or URL that you submit to VirusTotal for antivirus characterization, you might want to give visibility to your setup by automatically reviewing samples and URLs with the output of your automation.

In order to do so you can make use of VirusTotal's API by performing an HTTP POST request to the following URL:

https://www.virustotal.com/vtapi/v2/comments/put

You must provide the following HTTP POST parameters to the call:

  • resource: either a md5/sha1/sha256 hash of the file you want to review or the URL itself that you want to comment on.
  • comment: the actual review, you can tag it using the "#" twitter-like syntax (e.g. #disinfection #zbot) and reference users using the "@" syntax (e.g. @VirusTotalTeam).
  • apikey: your API key.

Some python code will hopefully illustrate better how this is done:

>>> import simplejson
>>> import urllib
>>> import urllib2
>>> url = "https://www.virustotal.com/vtapi/v2/comments/put"
>>> parameters = {"resource": "99017f6eebbac24f351415dd410d522d",
...               "comment": "How to disinfect you from this file... #disinfect #zbot",
...               "apikey": "-- YOUR API KEY --"}
>>> data = urllib.urlencode(parameters)
>>> req = urllib2.Request(url, data)
>>> response = urllib2.urlopen(req)
>>> json = response.read()
>>> print json
{"response_code": 1,
 "verbose_msg": "Your comment was successfully posted"}

If the comment was successfully posted the response code will be 1, 0 otherwise.

Scripts to interact with the public API

This section links several scripts written by VirusTotal Community members to interact with the public API using different programming languages. VirusTotal itself is not responsible for these scripts, they are contributions of the Community and their use is at your own risk. If you would like to see your own implementation listed in this section just get in touch with us.

Autoit
VirusTotal public API 2.0 implementation in Autoit thanks to @Danyfirex.
C / C++
VirusTotal public and private API 2.0 implementation in pure C done by VirusTotal team.
Delphi
VirusTotal public API implementation in Delphi thanks to Maxim Sysoev.
Elixir
VirusTotal API 2.0 implementation in Elixir Lang. Thanks to thanks to Doug
Erlang
VirusTotal public API implementation in Erlang thanks to dtykocki.
Go
VirusTotal public API 2.0 implementation in Go thanks to Willi Ballenthin.
VirusTotal public API 2.0 implementation in Go by dutchcoders.
Lua
VirusTotal public API 2.0 implementation in Lua by ner0x652.
Java
VirusTotal public API 2.0 implementation in Java thanks to Mauricio Correa.
VirusTotal public API 2.0 implementation in Java thanks to Kanishka Dilshan.
VirusTotal public API 2.0 implementation in Java thanks to BOJJA VIGHNESWAR RAO.
Maltego Transforms
Set of Maltego transforms for VirusTotal's public API contributed by Michael Yip.
VirusTotal Maltego transforms thanks to Lookingglass.
.NET
VirusTotal public API version 2.0 implementation in C#.NET thanks to Ian Qvist.
VirusTotal public API version 2.0 implementation in VB.NET thanks to omegatechware).
Implementation and Integration of VirusTotal's API in ASP.NET + Python. Thanks to Nilay Sangani
Node.js
An implementation of the Virustotal API for Node.js thanks to Nate Watson.
Perl
VirusTotal public API version 2.0 implementation in perl thanks to Michelle Sullivan from SORBS.
Perl script to submit files and retrieve their results thanks to Christopher Frenz (@cfrenz).
Perl script to check a sha256 hash against VirusTotal thanks to luckystrike.
perl script to check with MailScanner and generic-wrapeer sha256 signatures against virustotal thanks to luckystrike.
PHP
VirusTotal public API version 2.0, with internal PHP curl, and no other dependencies. Thanks to @IzzyOnDroid.
VirusTotal public API version 2.0 implementation in PHP thanks to @jayzeng.
PHP script for accessing VirusTotal public API Version 2.0 thanks to Andreas Breitschopp (@abtools).
PHP script for scanning files with VirusTotal public API Version 2.0 thanks to Adrian (@adrianTNT).
Powershell
VirusTotal public API version 2.0 implementation in Powershell thanks to @DBHeise.
Python
VirusTotal public API version 2.0 implementation in Python 2.x thanks to Chris Clark and Adam Meyers.
VirusTotal public API version 2.0 implementation in Python 2.x thanks to Gawen Arab.
VirusTotal public API version 2.0 implementation in Python 2.x thanks to @techno_vikiing.
Single and bulk lookups with VirusTotal public API version 2.0 thanks to Claudio Guarnieri.
VirusTotal public API version 2.0 implementation in Python 2.x thanks to @Erethon.
Full VirusTotal public and private API version 2.0 implementation in Python 2.x thanks to Andriy Brukhovetskyy.
VirusTotal public API version 2.0 implementation in Python 3.x thanks to Xiaokui Shu.
VirusTotal public API version 2.0 implementation in Python 2.x thanks to Phillip Martin.
VirusTotal Maltego transforms thanks to Lookingglass.
VirusTotal public and private API version 2.0 implementation in Python 2.x thanks to Blacktop.
VirusTotal domain scanner coded by Matthew Clairmont.
VirusTotal IP scanner coded by Matthew Clairmont.
VirusTotal public API version 2.0 implementation in Python coded by Tal Melamed.
Ruby
Rubygems command-line tool to interact with VirusTotal public API version 2.0 thanks to hammackj.
Ruby Gem for VirusTotal API version 2.0 thanks to pwelch.
XProc
XProc script to interact with VirusTotal public API version 2.0 thanks to Martin Kraetke.