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

VirusTotal's private API is a premium (billed) interface to VirusTotal's dataset and services. Unlike the public API, its request rate and total number of queries allowed is only limited by your own terms of service, in other words, with VirusTotal's private API your applications are not only easy to build and maintain, but also easy to scale as query throughput will not be a problem. Additionally, making use of Google's App Engine infrastructure, service availability is more than guaranteed.

This API can give you far more information than the public API on the items that you query for (files or URLs). This information includes VirusTotal related metadata (first seen and last seen dates, number of submissions, submission file names, etc.), file tool information (sigcheck, packer information, PE structure, sandbox analysis, etc.), complete scanning information (not only the latest report but all reports on a given sample, antivirus versions and signature updates, etc.), goodware information (goodware index, VirusTotal Community collective intelligence, aggregation of publicly available goodware databases, etc.) and any other data that you may think of and we can implement.

This API can be used in commercial products and services as long as they do not harm the antivirus industry directly or indirectly, and as long as they comply with VirusTotal's best practices . Non-compliance with this requirement will result in immediate termination of the service. More specifically, the users of this API have no restrictions in its use to improve their own database, research and security products. Having said this, the users are not allowed to sell the API results to third parties as returned by VirusTotal without any type of processing.

Getting started

The process could not be easier. Sign up to VirusTotal Community. Having 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 private API.

We also recommend you to install the Python Requests Library which you can find at http://docs.python-requests.org/. All the examples in this documentation are based in this library.

Once you have the key, contact us and ask us to set private API privileges on it.

Pricing model

As already stated, VirusTotal's private API is a premium billed service. Based on our customers' needs a set of query volume steps have been developed. Users pay a monthly fixed cost with independence of the number of requests so long as they stay within their chosen step, if they try to go over their licensed allowance the API will cap them. Please email for the different pricing options.

Note that certain API calls are only available if they have been specifically licensed, these calls are emphasized with a lock icon next to them.

API Summary

Resource Description
POST /vtapi/v2/file/scan Upload a file for scanning with VirusTotal.
GET /vtapi/v2/file/scan/upload_url Get a special URL to upload files bigger than 32MB in size.
POST /vtapi/v2/file/rescan Rescan a previously submitted file or schedule a scan to be performed in the future.
POST /vtapi/v2/file/rescan/delete Delete a previously scheduled scan.
GET /vtapi/v2/file/report Get the scan results for a file.
GET /vtapi/v2/file/behaviour Get a report about the behaviour of the file when executed in a sandboxed environment.
GET /vtapi/v2/file/network-traffic Get a dump of the network traffic generated by the file when executed.
POST /vtapi/v2/file/search Search for samples that match certain binary/metadata/detection criteria.
GET /vtapi/v2/file/clusters List file similarity clusters for a given time frame.
GET /vtapi/v2/file/feed Get a live feed with the lastest files submitted to VirusTotal.
GET /vtapi/v2/file/download Download a file by its hash.
GET /vtapi/v2/file/false-positives Consume file false positives from your notifications pipe.
POST /vtapi/v2/url/scan Submmit a URL for scanning with VirusTotal.
GET /vtapi/v2/url/report Get the scan results for a given URL.
GET /vtapi/v2/url/feed Get a live feed with the lastest URLs submitted to VirusTotal.
GET /vtapi/v2/ip-address/report Get information about a given IP address.
GET /vtapi/v2/domain/report Get information about a given domain.
POST /vtapi/v2/comments/put Post a comment on a file or URL.
GET /vtapi/v2/comments/get Get comments for a file or URL.

POST /vtapi/v2/file/scan

Allows you to send a file for scanning with VirusTotal. 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, in order to submmit files up to 200MB in size you must request a special upload URL.

Parameters
apikey Your API key.
notify_url
optional
A URL to which a POST notification should be sent when the scan finishes.
notify_changes_only
optional
Used in conjunction with notify_url. Indicates if POST notifications should be sent only if the scan results differ from the previous analysis.

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 in the JSON object lets you 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 once and over again, in other words, you should think of this as an asyncrhonous process. A good practice is to send a file an come back 1 hour later to request its results..

If the notify_url parameter was specified in the request, a POST request will be sent to the URL. The body of the POST request is a JSON-encoded dictionary with the following structure:

{
  'md5': '7896b9b34bdbedbe7bdc6d446ecb09d5',
  'sha1': '3828f4f998aefe0282e4c9cd642ac110dd3745d6'
  'sha256': 'dfcbeed0a07f24cded6deda71b07de9c30126c4155c2c20b90ac7c74bbf577f6',
  'scan_id': 'dfcbeed0a07f24cded6deda71b07de9c30126c4155c2c20b90ac7c74bbf577f6-1333539103'
  'scan_date': '2010-05-15 03:38:44',
  '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'},
    [...]
  }
}

Additionally, if the file was scanned before and you set the changes_only parameter to true, the dictionary will contain a previous_scans attribute with the same structure of scans. If previous_scans differs in some way from the current scan a differences attribute will appear. The differences attribute is a dictionary whose keys are the engine names changing their detection from one scan to the other, and the associated values are tuples in the form (current_signature, old_signature).

{
  'md5': '7896b9b34bdbedbe7bdc6d446ecb09d5',
  'sha1': '3828f4f998aefe0282e4c9cd642ac110dd3745d6'
  'sha256': 'dfcbeed0a07f24cded6deda71b07de9c30126c4155c2c20b90ac7c74bbf577f6',
  'scan_id': 'dfcbeed0a07f24cded6deda71b07de9c30126c4155c2c20b90ac7c74bbf577f6-1333539103'
  'scan_date': '2010-05-15 03:38:44',
  'scans': {
      'nProtect': {'detected': true, 'version': '2010-05-15.01', 'result': 'Trojan.Generic.4561280', 'update': '20100515'},
      'CAT-QuickHeal': {'detected': true, 'version': '10.00', 'result': 'Trojan.VB.acgy', 'update': '20100515'},
      'McAfee': {'detected': true, 'version': '5.400.0.1158', 'result': 'Generic.dx!rkx', 'update': '20100515'},
  },
  'previous_scans': {
      'nProtect': {'detected': true, 'version': '2010-05-14.01', 'result': 'Trojan.Generic.3611249', 'update': '20100514'},
      'CAT-QuickHeal': {'detected': false, 'version': '10.00', 'result': null, 'update': '20100514'},
      'McAfee': {'detected': true, 'version': '5.400.0.1158', 'result': 'Generic.dx!rkx', 'update': '20100514'},
  },
  'differences': {
      'nProtect': ('Trojan.Generic.4561280', 'Trojan.Generic.3611249'),
      'CAT-QuickHeal': ('Trojan.VB.acgy', null)
  }
}

GET /vtapi/v2/file/scan/upload_url

Special privileges! This API requires additional privileges. Please contact us if you need to upload files bigger than 32MB in size.

In order to submit files bigger than 32MB you need to obtain a special upload URL to which you can POST files up to 200MB in size. This API generates such a URL.

Parameters
apikey Your API key.

Example response:

{
  'upload_url': 'https://www.virustotal.com/_ah/upload/?apikey=>apikey</AMmfu6aOazgAdakralarFKHjJvxHdDiN5umGU9j5RzEfWPU8jQwtRgAM_LkxJlR24R0SCJ7MsIkWLD-C9nSraPSBwK7ujv84k3QNhzkSwX-GqcerFjSOZS25eHTQP6QBDyCXWAU4vEzIHcX1iigpcTbLrS9O9LnXQUs3Jn_kocDc61aDki2-Cm6ARN99JbAK82H8lWG3cBN1c4_WJbaeCDTNNnkky8Bfz8Qhxf327o_6GPAWVeeIt39TYTYL1e45-zwxFrqFHIWl/ALBNUaYAAAAAUQKBI1y6AfbKZLSO5QBdb2zDB0EYysh6/'
}

You can upload files to the provided URL in the same way you would do it to /vtapi/v2/file/scan. Here is a full example:

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-'}
# obtaining the upload URL
response = requests.get('https://www.virustotal.com/vtapi/v2/file/scan/upload_url', params=params)
json_response = response.json()
upload_url = json_response['upload_url']
file_path='mybigfile.exe'
# submitting the file to the upload URL
files = {'file': (file_path.decode('utf-8'), open(file_path, 'rb'))}
response = requests.post(upload_url, files=files)
print response
print response.text
        
URI='https://www.virustotal.com/vtapi/v2/file/scan/upload_url?'
KEY="apikey=${VT_API_KEY}"
REQ="${URI}${KEY}"
echo "Fetch Request: $REQ"

#NOTE using jsawk to make parsing easier: https://github.com/micha/jsawk

UPLOAD_URL=`curl -v --location ${REQ} | jsawk 'return this.upload_url'`
echo "Got upload URL: $UPLOAD_URL"

#upload the actual file
curl -v -F 'file=@/bin/mv' ${UPLOAD_URL}

        

//get API KEY from environment, or set your API key here
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';


$data = array('apikey' => $api_key);
$ch = curl_init();
$url = 'https://www.virustotal.com/vtapi/v2/file/scan/upload_url?';
$url .= http_build_query($data); // append query params
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True); // API will redirect
curl_setopt($ch, CURLOPT_URL, $url);
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);

$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);
  $upload_url=$js['upload_url'];
} else {  // Error occured
  print($result);
  return -1;
}
echo "upload_url:  $upload_url";

$file_name_with_full_path = realpath('/path/to/file');
$cfile = curl_file_create($file_name_with_full_path);

$post = array('file'=> $cfile);
curl_setopt($ch, CURLOPT_URL, $upload_url);
curl_setopt($ch, CURLOPT_POST, True);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); // set file

$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);
        

POST /vtapi/v2/file/rescan

This API allows you to rescan files present in VirusTotal's file store without having to resubmit them, thus saving bandwidth. You only need to know one of the hashes of the file to rescan.

Use with care! This API does not subject you to file upload latencies and so has the potential to produce a denial of service on the scanning infrastrucutre if abused. Please contact us if you are going to be rescanning more than 50K files per day.
Parameters
apikey Your API key.
resource An 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 just one single call. Note that the file must already be present in our file store.
date
optional
Date in %Y%m%d%H%M%S format (example: 20120725170000) in which the rescan should be performed. If not specified the rescan will be performed immediately.
period
optional
Periodicity (in days) with which the file should be rescanned. If this argument is provided the file will be rescanned periodically every period days, if not, the rescan is performed once and not repated again.
repeat
optional
Used in conjunction with period to specify the number of times the file should be rescanned. If this argument is provided the file will be rescanned the given amount of times in coherence with the chosen periodicity, if not, the file will be rescanned indefinitely.
notify_url
optional
A URL to which a POST notification should be sent when the rescan finishes.
notify_changes_only
optional
Used in conjunction with notify_url. Indicates if POST notifications should only be sent if the scan results differ from the previous one.

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',
}

POST /vtapi/v2/file/rescan/delete

Deletes a scheduled file rescan task. The file rescan api allows you to schedule periodic scans of a file, this API call tells VirusTotal to stop rescanning a file that you have previously enqueued for recurrent scanning.

Parameters
apikey Your API key.
resource An md5/sha1/sha256 hash of a file which you want to remove from periodic scanning.
import requests
params = {'apikey': '-YOUR API KEY HERE-', 'resource': '7657fcb7d772448a6d8504e4b20168b8'}
response = requests.post('https://www.virustotal.com/vtapi/v2/file/rescan/delete', params=params)
json_response = response.json()

Example response:

{u'response_code': 1, u'resource': u'7657fcb7d772448a6d8504e4b20168b8'}

In the event that the scheduled scan deletion fails for whatever reason, the response code will be -1.

GET /vtapi/v2/file/report

Retrieves a concluded file scan report for a given file. Unlike the public API, this call allows you to also access all the information we have on a particular file (VirusTotal metadata, signature information, structural information, etc.) by using the allinfo parameter described later on. You may use either HTTP GET or POST with this API call.

Parameters
apikey Your API key.
resource An md5/sha1/sha256 hash of a file for which you want to retrieve the most recent antivirus report. You may also specify a scan_id (sha256-timestamp as returned by the scan 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 25 items), this allows you to perform a batch request with just one single call.
allinfo
optional
If specified and set to one, the call will return additional info, other than the antivirus results, on the file being queried. This additional info includes the output of several tools acting on the file (PDFiD, ExifTool, sigcheck, TrID, etc.), metadata regarding VirusTotal submissions (number of unique sources that have sent the file in the past, first seen date, last seen date, etc.), the output of in-house technologies such as a behavioural sandbox, etc.

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/'
}

GET /vtapi/v2/file/behaviour

VirusTotal runs a distributed setup of Cuckoo sandbox machines that execute the files we receive. Execution is attempted only once, upon first submission to VirusTotal, and only Portable Executables under 10MB in size are ran. The execution of files is a best effort process, hence, there are no guarantees about a report being generated for a given file in our dataset.

If a file did indeed produce a behavioural report, a summary of it can be obtained by using the file scan lookup call providing the additional HTTP POST parameter allinfo=1. The summary will appear under the behaviour-v1 property of the additional_info field in the JSON report.

This API allows you to retrieve the full JSON report of the file's execution as returned by the Cuckoo JSON report encoder.

Parameters
apikey Your API key.
hash The md5/sha1/sha256 hash of the file whose dynamic behavioural report you want to retrieve.

Example:

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'hash': '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/behaviour',
  params=params, headers=headers)
json_response = response.json()
        
URI='https://www.virustotal.com/vtapi/v2/file/behaviour?'
KEY="apikey=${VT_API_KEY}"
HASH='hash=44cda81782dc2a346abd7b2285530c5f'
REQ="${URI}${KEY}&${HASH}"
echo "Fetch Request: $REQ"
curl -v --request GET --location --url ${REQ}
        
$ch = curl_init();
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';
$data = array('apikey' => $api_key,
  'hash'=>'bf1635385fdf1a4c33b98164009e85a69a71347a388f7631e1c243d95695e54c');
$url = 'https://www.virustotal.com/vtapi/v2/file/behaviour?';
$url .= http_build_query($data); // append query params
echo "URL: $url";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
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_FOLLOWLOCATION, True); // API will redirect
curl_setopt($ch, CURLOPT_RETURNTRANSFER ,true);

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

Example response:

{
  'info': {'started': '2012-08-26 17:01:53',
          'duration': '76 seconds',
          'version': 'v0.1',
          'ended': '2012-08-26 17:03:10'},

 'network': {'hosts': ['0.0.0.0', '255.255.255.255', '10.0.2.2', '10.0.2.15',
                       '239.255.255.250', '213.133.100.100', '65.55.21.22',
                       '224.0.0.22', '10.0.2.255', '66.77.96.107', '93.184.220.20',
                       '23.14.93.48', '67.134.208.160', '199.7.52.190', '66.235.120.94',
                       '74.113.233.61', '173.194.39.98', '173.194.39.103', '95.140.237.13'],

             'udp': [{'dport': 67, 'src': '0.0.0.0', 'dst': '255.255.255.255'

             [... report continues ...]
}

If there is no behavioural report for the queried file, you have provided an erroneous hash or the requested file is not in our dataset the JSON returned will contain a response_code property set to 0 and a verbose_msg field with information on why no report was found for the requested file.

GET /vtapi/v2/file/network-traffic

VirusTotal runs a distributed setup of Cuckoo sandbox machines that execute the files we receive. Execution is attempted only once, upon first submission to VirusTotal, and only Portable Executables under 10MB in size are ran. The execution of files is a best effort process, hence, there are no guarantees about a report being generated for a given file in our dataset.

Files that are successfully executed may communicate with certain network resources, all this communication is recorded in a network traffic dump (pcap file). This API allows you to retrieve the network traffic dump generated during the file's execution.

Parameters
apikey Your API key.
hash The md5/sha1/sha256 hash of the file whose network traffic dump you want to retrieve.

Example Code:

#!/usr/bin/python
import requests
import os

vt_api_key = os.getenv('VT_API_KEY', '---YOUR-API-KEY---')
if not vt_api_key:
  sys.stderr.write("Set  VT_API_KEY  environment variable with your API key \n")
  sys.exit(1)


def get_net_traffic():

  params = {'apikey': vt_api_key,
    'hash': '9348d86a34a47e6094051173a64132c4a52ae8ecba86d3799f1a8c6889729744'}

  headers = {
    "Accept-Encoding": "gzip, deflate",
    "User-Agent" : "gzip,  My Python requests library example client or username"
  }

  first_bytes = None
  with open('traffic.pcap', 'wb') as handle:
    response = requests.get('https://www.virustotal.com/vtapi/v2/file/network-traffic', \
      params=params, headers=headers, stream=True)

    if not response.ok:
      print "something is wrong %s" % (response)
      return

    for block in response.iter_content(4096):
      handle.write(block)
      if not first_bytes:
        first_bytes = str(block)[:4]

    valid_pcap_magics = [ '\xd4\xc3\xb2\xa1',
      '\xa1\xb2\xc3\xd4', '\x4d\x3c\xb2\xa1', '\xa1\xb2\x3c\x4d' ]
    if first_bytes in valid_pcap_magics:
      print "PCAP downloaded"
    elif first_bytes.startswith('{"'):
      print "NOT found"
    else:
      print "unknown file"

get_net_traffic()
        
curl -v --request GET --location \
"https://www.virustotal.com/vtapi/v2/file/network-traffic?\
apikey=${VT_API_KEY}&hash=44cda81782dc2a346abd7b2285530c5f" -o out.pcap
        

If there is no network traffic dump for the queried file, you have provided an erroneous hash or the requested file is not in our dataset a JSON object will be returned, it will contain a response_code property set to 0 and a verbose_msg field with information on why no traffic dump was found for the requested file.

Daily limited! No matter what API step you have licensed, this API call is limited to 50K requests per day. If you need any more, chances are you are approaching your engineering problem erroneously and you can probably solve it using the file feed call. Do not hesitate to contact us with your particular use case.

In addition to retrieving all information on a particular file, VirusTotal allows you to perform what we call "advanced reverse searches". Reverse searches take you from a file property to a list of files that match that property. For example, this functionality enables you to retrieve all those files marked by at least one antivirus vendor as Zbot, or all those files that have a size under 90KB and are detected by at least 10 antivirus solutions, or all those PDF files that have an invalid XREF section, etc.

You may use either GET or POST with this request. If your using GET you must keep the total URL length under 1024 characters.

This API is equivalent to VirusTotal Intelligence advanced searches. A very wide variety of search modifiers are available, including: file size, file type, first submission date to VirusTotal, last submission date to VirusTotal, number of positives, dynamic behavioural properties, binary content, submission file name, and a very long etcetera. The full list of search modifiers allowed for file search queries is documented at:

https://www.virustotal.com/intelligence/help/file-search/#search-modifiers

Please note that you must be logged in with a valid VirusTotal Community user account in order to be able to view the full list of search modifiers.

All of the API responses are JSON objects, if no files matched your query this JSON will have a response_code property equal to 0, if there was some sort of error with your query this code will be set to -1, if your query succeded and files were found it will have a value of 1 and a list of SHA256 hashes matching the queried properties will be embedded in the object.

Parameters
apikey Your API key.
query A search modifier compliant file search query.
offset
optional
The offset value returned by a previously issued identical query, allows you to paginate over the results. If not specified the first 300 matching files sorted according to last submission date to VirusTotal in a descending fashion will be returned.

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-', 'query': 'type:peexe size:90kb+ positives:5+ behaviour:"taskkill"'}
response = requests.post('https://www.virustotal.com/vtapi/v2/file/search', data=params, headers=headers)
response_json = response.json()
        
curl -v --request POST --location \
  -d apikey=${VT_API_KEY} \
  -d "query=type:peexe+positives:5++" \
https://www.virustotal.com/vtapi/v2/file/search
        

Example response:

{
  'response_code': 1,
  'offset': 'RmFsc2 ... JQUVEb0J3',
  'hashes': [
              'c9bfeaf31115dccfe033f67c3b56453a5e434e2e39a2dcf76d80c05603ef9cda',
              '510c0c513b10ebec6ed5d577d8e4701950beb61bbc48f99a61c4780ba58e5fb9',
              .
              .
              .
              '32aef41d79c9bca51c1aa63d1625abc721d2518e133b8667bcca9c4f0c4a60a6',
            ]
}

As you can observe, calls to this function return a list of criteria-matching hashes, in order to access the information of the files with those hashes you must then make use of the file report retrieving API call. By default the list returned contains at most 300 hashes, ordered according to last submission date to VirusTotal in a descending fashion. If there are more results available to paginate over, the offset property will be embedded in the JSON object returned, you can then issue exactly the same query with the additional HTTP POST parameter offset fixed to such value and you will retrieve the next 300 hashes matching your query.

GET /vtapi/v2/file/clusters

VirusTotal has built its own in-house file similarity clustering functionality. At present, this clustering works only on PE, PDF, DOC and RTF files and is based on a very simple structural feature hash. This hash can very often be confused by certain compression and packing strategies, in other words, this clustering logic is no holly grail, yet it has proven itself very useful in the past.

This API offers a programmatic access to the clustering section of VirusTotal Intelligence:

https://www.virustotal.com/intelligence/clustering/

Please note that you must be logged in with a valid VirusTotal Community user account with access to VirusTotal Intelligence in order to be able to view the clustering listing.

All of the API responses are JSON objects, if no clusters were identified for the given time frame, this JSON will have a response_code property equal to 0, if there was some sort of error with your query this code will be set to -1, if your query succeded and file similarity clusters were found it will have a value of 1 and the rest of the JSON properties will contain the clustering information.

Parameters
apikey Your API key.
date A specific day for which we want to access the clustering details, example: 2013-09-10.

Example:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'date': '2013-09-10'}
response = requests.get('https://www.virustotal.com/vtapi/v2/file/clusters', params=params)
response_json = response.json()

Example response:

{
  'response_code': 1,
  'verbose_msg': u'Clustering information enclosed',
  'clusters': [
    {'label': 'vilsel [0001]', 'avg_positives': 43, 'id': 'vhash 0740361d051)z1e3z 2013-09-10', 'size': 5712},
    {'label': 'installer [0032]', 'avg_positives': 7, 'id': 'vhash 02503e0f7d5019z6hz13z1fz 2013-09-10', 'size': 4710},
    {'label': 'megasearch [0000]', 'avg_positives': 12, 'id': 'vhash 075056651d1d155az639z25z12z14fz 2013-09-10', 'size': 3651},
    [... continues ...]
  'num_candidates': 184701,
  'num_clusters': 44269,
  'size_top200': 85160
}

As you can observe, the JSON object contains several properties, some of them may not be clear, the following table provides some further insight:

Response fields
num_candidates Total number of files submitted during the given time frame for which a feature hash could be calculated.
num_clusters Total number of clusters generated for the given time period under consideration, a cluster can be as small as an individual file, meaning that no other feature-wise similar file was found.
size_top200 The sum of the number of files in the 200 largest clusters identified.
clusters List of JSON objects that contain details about the 200 largest clusters identified. These objects contain 4 properties: id, label, size and avg_positives.. The id field can be used to then query the search API call for files contained in the given cluster. The label property is a verbose human-intelligible name for the cluster. The size field is the number of files that make up the cluster. Finally, avg_positives represents the average number of antivirus detections that the files in the cluster exhibit.

As said, the id property of each cluster allows users to list files contained in the given cluster by using the search API call, the query syntax is as follows:

import requests
cluster_id = 'vhash 0740361d051)z1e3z 2013-09-10'
params = {'apikey': '-YOUR API KEY HERE-', 'query': 'cluster:"%s"' % cluster_id}
response = requests.get('https://www.virustotal.com/file/clusters', params=params)
json_response = response.json()

GET /vtapi/v2/file/feed

Special privileges! This API call is only available to users that have licensed the file feed separately from the other API calls.

Allows you to retrieve a live feed of absolutely all uploaded files to VirusTotal, and download them for further scrutiny, along with their full reports. This API requires you to stay relatively synced with the live submissions as only a backlog of 24 hours is provided at any given point in time.

Parameters
apikey Your API key.
package Indicates a time window to pull reports on all items received during such window. Only per-minute and hourly windows are allowed, the format is %Y%m%dT%H%M (e.g. 20160304T0900) or %Y%m%dT%H (e.g. 20160304T09). Time is expressed in UTC.

This API returns a bzip2 compressed tarball. For per-minute packages the compressed package contains a unique file, the file contains a json per line, this json is a full report on a given file processed by VirusTotal during the given time window. The file report follows the exact same format as the response of the file report API if the allinfo=1 parameter is provided. For hourly packages, the tarball contains 60 files, one per each minute of the window.

To download a given file you would then perform an HTTP GET request to the URL provided in the link property of an individual report. Do not use the file download API to retrieve the corresponding file, please use the link embedded in this response, it is far more efficient.

Example:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'package': '20160304T0700'}
response = requests.get('https://www.virustotal.com/vtapi/v2/file/feed', params=params)
package_file = open('file-20160304T0700.tar.bz2', 'wb')
package_file.write(response.content)
package_file.close()

Note that you can only request packages pertaining to the last 24 hours. You should stay approximately 5 minutes behind the current UTC time in order to make sure that all items have been correctly packaged and the compressed bundle has been uploaded to the cloud storage.

We have put together a very simple Python script that exemplifies how you can use this API in order to download the files received during a given hourly or minute time window.

Download the file feed python script

You will obviously have to tweak the script in order to store the files as desired or feed the file reports into a local database.

GET /vtapi/v2/file/download

Downloads a file from VirusTotal's store given one of its hashes. This call can be used in conjuction with the file searching call in order to download samples that match a given set of criteria.

Parameters
apikey Your API key.
hash The md5/sha1/sha256 hash of the file you want to download.

If the file is not found in the store you will receive an HTTP 404 response, you will be returned the requested binary content otherwise. Under special circumstances you may receive some other HTTP error response, this denotes a transient issue with the store, when this happens you should retry the download.

Example Code:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'hash': '44cda81782dc2a346abd7b2285530c5f'}
response = requests.get('https://www.virustotal.com/vtapi/v2/file/download', params=params)
downloaded_file = response.content
        
curl -v --location https://www.virustotal.com/vtapi/v2/file/download?\
apikey=${VT_API_KEY}\&hash=44cda81782dc2a346abd7b2285530c5f -o sample.bin
        

GET /vtapi/v2/file/false-positives

Attention! This API is only available to antivirus vendors participating in VirusTotal. If you are one such vendor contact us to set up your access. Additionally, all calls to this endpoint should set two HTTP request headers: "Accept-Encoding: gzip" and "User-Agent: gzip", otherwise you will receive 400 Bad Request Errors.

This call allows vendors to consume false positive notifications for files that they mistakenly detect.

VirusTotal has partnered up with certain large trusted software developers of legit applications in order to mark files that unambiguously belong to these companies. Whenever one such file is detected by a given antivirus vendor its details and download link are published in the vendor's false positive notification pipe. The aim of this is to provide early remediation to false positives, which are a business hazard for developers and reputation/press chaos for antivirus solutions.

Parameters
apikey Your API key.
limit The number of false positive notification to consume, if available. The maximum value for this parameter is 1000.

This call returns a JSON response, when decoded it becomes a list/array, with one object per false positive notification. This object contains all the details on the given file, including a 48h link to be able to download it. The object's contents are exactly the same as those reuturned by the file report API call.

Example:

import requests
headers = {'User-Agent': 'gzip', 'Accept-Encoding': 'gzip'}
params = {'apikey': '-YOUR API KEY HERE-', 'limit': 500}
response = requests.get('https://www.virustotal.com/vtapi/v2/file/false-positives', params=params, headers=headers)
false_positives = response.json()

The idea of this call is that you will keep calling it while it answers back with as many notifications as you asked for with the limit parameter. In the event that less than such limit are returned, you will sleep for, for example, 5 minutes and then ask again for new notifications.

Please note that once you retrieve a set of false positive notifications these will not appear ever again in your pipe, hence, make sure there is only one team consuming these requests at your side and make sure that you do get to process retrieved false positives.

POST /vtapi/v2/url/scan

Allows you to submit URLs to be scanned by VirusTotal. 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.

Parameters
apikey Your API key.
url The URL that should be scanned. This parameter accepts a list of URLs so as to perform a batch scanning request with just one single call (up to 25 URLs per call). The URLs must be separated by a new line character.
Response fields
permalink A permalink that can be displayed in a user interface with full details
scan_id A unique scan ID for this scan. You can use this scan id for checking the report.
scan_date Date and time of the scan in UTC timezone.
url the URL being scanned
resource rescource being scanned
response_code -1 : Invalid URL
1: Successfully queued up the scan
verbose_msg Verbose response message of status.

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': '2011-11-08 11:39:24',
  'url': 'http://www.virustotal.com/',
  'permalink': 'http://www.virustotal.com/url/1db0ad7dbcec0676710ea0eaacd35d5e471d3e11944d53bcbd31f0cbd11bce31/analysis/1320752364/'
}

The scan_id parameter in 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.

GET /vtapi/v2/url/report

Retrieves a concluded scan report for a given URL, this report contains maliciousness verdicts as produced by different antivirus solutions, URL scanners and malicious URL datasets.

Parameters
apikey Your API key.
resource A URL for which you want to retrieve the most recent report. 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 urls and scan_ids (up to 25 items) so as to perform a batch request with one single call. The CSV list must be separated by new line characters. NOTE: If you have a large batch, or are checking long URLs, you should use POST because it's possible to go over the 1024 character limt of GET.
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.
allinfo
optional
If this parameter is specified and set to "1" additional info regarding the URL (other than the URL scanning engine results) will also be returned. This additional info includes VirusTotal related metadata (first seen date, last seen date, files downloaded from the given URL, etc.) and the output of other tools and datasets when fed with the URL.

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 ...]
  }
}

GET /vtapi/v2/url/feed

Special privileges! This API call is only available to users that have licensed the url feed separately from the other API calls.

Allows you to retrieve a live feed of reports on absolutely all URLs scanned by VirusTotal. This API requires you to stay relatively synced with the live submissions as only a backlog of 24 hours is provided at any given point in time.

Parameters
apikey Your API key.
package Indicates a time window to pull reports on all items received during such window. Only per-minute and hourly windows are allowed, the format is %Y%m%dT%H%M (e.g. 20160304T0900) or %Y%m%dT%H (e.g. 20160304T09). Time is expressed in UTC.

This API returns a bzip2 compressed tarball. For per-minute packages the compressed package contains a unique file, the file contains a json per line, this json is a full report on a given URL processed by VirusTotal during the given time window. The URL report follows the exact same format as the response of the URL report API if the allinfo=1 parameter is provided. For hourly packages, the tarball contains 60 files, one per each minute of the window.

Example:

import requests
params = {'apikey': '-YOUR API KEY HERE-', 'package': '20160304T0700'}
response = requests.get('https://www.virustotal.com/vtapi/v2/url/feed', params=params)
package_file = open('url-20160304T0700.tar.bz2', 'wb')
package_file.write(response.content)
package_file.close()

Note that you can only request packages pertaining to the last 24 hours. You should stay approximately 5 minutes behind the current UTC time in order to make sure that all items have been correctly packaged and the compressed bundle has been uploaded to the cloud storage.

We have put together a very simple Python script that exemplifies how you can use this API in order to download the files received during a given hourly or minute time window.

Download the file feed python script

You will obviously have to tweak the script in order to feed the URL reports into a local database or visit the pertinent URLs with honeyclients and the like.

GET /vtapi/v2/ip-address/report

Retrieves a report on a given IP address (including the information recorded by VirusTotal's Passive DNS infrastructure).

Query Parameters
apikey Your API key.
ip A valid IPv4 address in dotted quad notation, for the time being only IPv4 addresses are supported.
Response Fields
asn autonomous system number (ASN)
as_owner The owner name of the autonomous system.
country Country where IP Address is located.
resolutions Hostnames that have resolved to this IP address. We resolve it when a file or URL related to this IP address is seen on VirusTotal.
detected_urls URLs hosted at this IP address that have url scanner postive detections.
detected_communicating_samples Latest 100 files submitted to VirusTotal that are detected by one or more antivirus solutions and communicate with the IP address provided when executed in a sandboxed environment.
undetected_downloaded_samples Latest 100 files that have been downloaded from this IP address, with no antivirus detections.
response_code -1 : Invalid IP address
0 : IP Address not in our dataset
1: Successfully found IP address
verbose_msg Verbose response message of status.

Example Code:

import requests
params = {'ip': '90.156.201.27', 'apikey': '-- YOUR API KEY --'}
headers = {
  "Accept-Encoding": "gzip, deflate",
  "User-Agent" : "gzip,  My python example client or username"
}
response = requests.get('https://www.virustotal.com/vtapi/v2/ip-address/report',
  params=params, headers=headers)
response_json = response.json()
        
#!/bin/bash

URI='https://www.virustotal.com/vtapi/v2/ip-address/report?'
KEY="apikey=${VT_API_KEY}"
IP='ip=8.8.8.8'
REQ="${URI}${KEY}&${IP}"
echo "Fetch Request: $REQ"
curl -v --request GET  --url ${REQ}
        
//get API KEY from environment, or set your API key here
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';
$report_ip = '8.8.8.8';


$data = array('apikey' => $api_key,'ip'=> $report_ip);
$ch = curl_init();
$url = 'https://www.virustotal.com/vtapi/v2/ip-address/report?';
$url .= http_build_query($data); // append query params
curl_setopt($ch, CURLOPT_URL, $url);
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);

$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);
        
var request = require('request');

var apikey = process.env.VT_API_KEY || 'YOUR-API-KEY'
var url='https://www.virustotal.com/vtapi/v2/ip-address/report';
var qs = {
  'apikey' : apikey,
  'ip' : '8.8.8.8'
};

var options = {
  url : url,
  qs : qs,
  json : true,
  gzip : true,
  headers: {
    'User-Agent': 'gzip, node.js requests client example'
  }
};

request.get(options, function (err, msg, response) {
  if (err) {
    console.error("Error Occured");
    console.error(err);
    return;
  }
  if (msg.statusCode == 200) {
    console.log('OK Got respsonse');
    console.log(response);
  } else {
   console.error("Handle some error status code");
   console.log(msg);
   console.log(response);
  }
});

        

Example response:

{
  'response_code': 1,
  'verbose_msg': 'IP address found in dataset',
  'resolutions': [
      {'last_resolved': '2013-04-08 00:00:00', 'hostname': u'027.ru'},
      {'last_resolved': '2013-04-08 00:00:00', 'hostname': u'auto.rema-tiptop.ru'},
      {'last_resolved': '2013-04-08 00:00:00', 'hostname': u'catalog24de.ru'},
      {'last_resolved': '2013-04-08 00:00:00', 'hostname': u'club.velhod.ru'},
      {'last_resolved': '2013-04-08 00:00:00', 'hostname': u'danilova.pro'},
      [... continues ...]
  ],
  'detected_urls': [
      {"url": "http://027.ru/", "positives": 2, "total": 37, "scan_date": "2013-04-07 07:18:09"},
      [... continues ...]
  ]
}

Full example response:

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 has increased 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.

GET /vtapi/v2/domain/report

Retrieves a report on a given domain (including the information recorded by VirusTotal's passive DNS infrastructure).

Parameters
apikey Your API key.
domain A domain name.
Response Fields
subdomains A domain which is part of a primary domain. For example mail.google.com is a subdomain of google.com
domain_siblings Domains which have a common parent. For example mail.google.com, drive.google.com and news.google.com are sibilings.
resolutions IP addresses that this domain resolves to. We resolve it when a file or URL related to this IP address is seen on VirusTotal.
detected_urls URLs hosted at this IP address that have url scanner postive detections.
detected_communicating_samples Latest 100 files submitted to VirusTotal that are detected by one or more antivirus solutions and communicate with the IP address provided when executed in a sandboxed environment.
undetected_downloaded_samples Latest 100 files that have been downloaded from this IP address, with no antivirus detections.
detected_referrer_samples 100 Most recent samples that contain the given domain among their strings and detected by at least one AV.
undetected_referrer_samples 100 Most recent samples that contain the given domain among their strings and not detected by at least one AV.
response_code -1 : Invalid domain
0 : Domain not in our dataset
1: Successfully found
verbose_msg Verbose response message of status.

Example Code:

import requests
params = {'domain': '027.ru', 'apikey': '-- YOUR API KEY --'}
headers = {
  "Accept-Encoding": "gzip, deflate",
  "User-Agent" : "gzip,  My python example client or username"
}
response = requests.get('https://www.virustotal.com/vtapi/v2/domain/report',
  params=params, headers=headers)
response_json = response.json()
        
#!/bin/bash

URI='https://www.virustotal.com/vtapi/v2/domain/report?'
KEY="apikey=${VT_API_KEY}"
DOMAIN='domain=drive.google.com'
REQ="${URI}${KEY}&${DOMAIN}"
echo "Fetch Request: $REQ"
curl -v --request GET  --url ${REQ}
        
//get API KEY from environment, or set your API key here
$api_key = getenv('VT_API_KEY') ? getenv('VT_API_KEY') :'YOUR_API_KEY';
$domain = 'drive.google.com';


$data = array('apikey' => $api_key,'domain'=> $domain);
$ch = curl_init();
$url = 'https://www.virustotal.com/vtapi/v2/domain/report?';
$url .= http_build_query($data); // append query params
curl_setopt($ch, CURLOPT_URL, $url);
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);

$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": "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 has increased 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.

POST /vtapi/v2/comments/put

Allows you to place comments on URLs and files, these comments will be publicly visible in VirusTotal Community, under the corresponding tab in the reports for each particular item.

Comments can range from URLs and locations where a given file was found in the wild to full reverse engineering reports on a given malware specimen, anything that may help other analysts in extending their knowledge about a particular file or URL.

Parameters
apikey Your API key.
resource Either an 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).

Example:

import requests
params = {
  'apikey': '-YOUR API KEY HERE-',
  'resource':'99017f6eebbac24f351415dd410d522d',
  'comment': 'How to disinfect you from this file... #disinfect #zbot'
}
response = requests.post('https://www.virustotal.com/vtapi/v2/comments/put', params=params)
response_json = response.json()

Example response:

{'response_code': 1, 'verbose_msg': 'Your comment was successfully posted'}

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

GET /vtapi/v2/comments/get

Retrieve a list of VirusTotal Community comments for a given file or URL. VirusTotal Community comments are user submitted reviews on a given item, these comments may contain anything from the in-the-wild locations of files up to fully-featured reverse engineering reports on a given sample.

Parameters
apikey Your API key.
resource Either an md5/sha1/sha256 hash of the file or the URL itself you want to retrieve.
before
optional
A datetime token that allows you to iterate over all comments on a specific item whenever it has been commented on more than 25 times.

The application answers with the comments sorted in descending order according to their date. Please note that, for timeout reasons, the application will only answer back with at most 25 comments. If the answer contains less than 25 comments it means that there are no more comments for that item. On the other hand, if 25 comments were returned you should keep issuing further calls making use of the optional before parameter, this parameter should be fixed to the oldest (last in the list) comment's date token, exactly in the same formatthat was returned by your previous API call (e.g. 20120404132340).

Example:

import requests
params = {
  'apikey': '-YOUR API KEY HERE-',
  'resource':'99017f6eebbac24f351415dd410d522d'
  }
response = requests.get('https://www.virustotal.com/vtapi/v2/comments/get', params=params)
response_json = response.json()

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':'99017f6eebbac24f351415dd410d522d'
  }
response = requests.get('https://www.virustotal.com/vtapi/v2/comments/get',
  params=params, headers=headers)
response_json = response.json()

        
curl -v "https://www.virustotal.com/vtapi/v2/comments/get?\
apikey=${VT_API_KEY}&resource=7f0800e339d2f6a139df128eb78c00df"
        

Example response:

{
  'response_code': 1,
  'verbose_msg': 'Resource found, comments, if any, returned here',
  'resource': '13166fc9de263ee2c676430ae88e65040e10761c90e79347a2684476bc60e622',
  'comments': [
      {'date': '20120404132340',
       'comment': '[b]Bot Communication Details:[\/b]\nServer DNS Name: 67.230.163.30
                   Service Port: 80\nDirection Command User-Agent Host Connection
                   Pragma\nGET \/?0b72ab=huTK4N7k6G9718ze0NLa5%2BnM1NaHx9fXtqfeyr
                   FjiKSbxZ%2BmmqOjpqeXZqPPnpOhnda\nrpJ2bkpfLyZdk0MqokZNplofO5aKh
                   [... continues ...]'},

      {'date': '20120404132122',
       'comment': '#fakeAV'},

      {'date': '20120404131639',
       'comment': 'GET \/ury1007_8085.php?il41225lo=jeWqkqWocs3h1NDHi6Lcx56mlaqol
                   tnVmG5lWJbO0eWeuqZ6w4nN4aKjo6CgkqOkb6mrxL%2BZw8%2FJatXCqrOdmO3
                   S16mjl5eUnNbemcTJooLGicreoqOpp5eeZ2pgY26aoaOUjNih1NfW4aKjmefS0
                   HFiYmRrkuPnzaPGXtSYx6KepaWkopKopG9jaJ%2BiqJWamWWjicXd0tPc3qbjq
                   6hlYKXR4ebQ1MaZoNDC4dnX5eLUmpiVoKVj1d3Z0IzPpNnXnuPb6d%2Fm0ZKnp
                   pR1otCs5sbUyXPcz8aS HTTP\/1.1\nAccept: image\/gif, image\/jpeg
                   , image\/pjpeg, image\/pjpeg, application\/x-shockwave-flash,
                   application\/vnd.ms-excel, application\/vnd.ms-powerpoint,
                   [... continues ...]'}
  ],
}

If there were any comments at all the response code will be 1, 0 otherwise. Please note that comments may have bbcode formatting tags in them.