Manpage logo

vt-py - vt-py Documentation

NAME  HOW TO INSTALL  OVERVIEW  QUICKSTART  Get information about a file  Get information about an URL  Scan a file  Scan an URL  Download a file  Start and abort a Retrohunt job  Create a LiveHunt ruleset  Closing  API REFERENCE  Client  Feed  Object  Iterator  Utility functions  AUTHOR  COPYRIGHT 

NAME

vt-py − vt-py Documentation

vt−py is the official Python client library for the VirusTotal API v3.

This library requires Python 3.7.0+, Python 2.x is not supported. This is because vt−py makes use of the new async/await syntax for implementing asynchronous coroutines.

Not supporting Python 2.x was a difficult decision to make, as we are aware that Python 2.x is still popular among VirusTotal users, but in the long run we think it's the right one.

Python 2.7 has its days numbered, and the new concurrency features included in Python 3.5+ are perfect for creating highly performant code without having to deal with multi−threading or multi−processing.

HOW TO INSTALL

The easiest and recommended way of installing vt−py is using pip:

$ pip install vt−py

Alternatively, you can get the source code directly from the GitHub and run setup.py. For getting the code you can either clone the public repository:

$ git clone https://github.com/VirusTotal/vt−py.git
$ cd vt−py

Or, download the tarball for the latest release and uncompress it:

$ tar −zxvf vt−py−X.Y.Z.tar.gz
$ cd vt−py−X.Y.Z

Once you have the code you can install it with:

$ pip install .

OVERVIEW

The API for this library is relatively small and shares the same concepts and principles seen in the underlying REST API. For this reason we highly recommend you to familiarize yourself with these - concepts before continuing.

While using this library you may have the impression that it's very similar to other general−purpose HTTP libraries like requests, as you will see very generic APIs like vt.Client.get(), vt.Client.post() and so on. In fact, you will find yourself relying on the REST API documentation in order to find the right endpoint where to send a request to, or learn about the attributes exported by some object. This has been a deliberate decision. We wanted vt−py to be as lightweight and generic as possible, so that changes in the REST API don't always require a new version of this client library, but at the same time offering the right abstractions so that you don't need to deal with details like setting HTTP headers, serializing and deserializing JSON, etc.

So, this is not a high−level library that completely abstract you out of the underlying REST API, quite the contrary, this library is more like a HTTP library that has been enriched with features specifically tailored to work with the VirusTotal API.

QUICKSTART

Get information about a file

Start by importing the vt module:

>>> import vt

Create a client, replace <apikey> with your actual VirusTotal API key:

>>> client = vt.Client("<apikey>")

Ask for the file you are interested in, you can replace the hash in the example with some other SHA−256, SHA−1 or MD5:

>>> file = client.get_object("/files/44d88612fea8a8f36de82e1278abb02f")

Now file is an instance of vt.Object that contains information about the requested file. This object have the attributes returned in the API response which are listed in the VirusTotal API v3 documentation. Some examples:

>>> file.size
68

>>> file.sha256
'275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f'

>>> file.type_tag
'text'

>>> file.last_analysis_stats
{'failure': 0, 'harmless': 0, 'malicious': 62, 'suspicious': 0, 'timeout': 0, 'type−unsupported': 9, 'undetected': 2}

Alternatively, you can use the vt.Object.get() method for retrieving object's attributes:

>>> file.get("size")
68

>>> file.get("type_tag")
'text'

This method is useful for those attributes that are optional and do not appear in all files. For example, a Portable Executable (PE) file won't have the pdf_info attribute, and PDF document won't have the pe_info attribute. This means that file.pe_info will fail for PDF files but with file.get("pe_info") you are on the safe side, as it will return None if the pe_info attribute is not present.

Get information about an URL

Create a client as explained in the previous section and ask for the desired URL as follows:

>>> url_id = vt.url_id("http://www.virustotal.com")
>>> url = client.get_object("/urls/{}", url_id)

In this case the code is not as straightforward as it was for getting a file. While retrieving a file any of its hashes can be used as the file identifier, but with URLs is a bit more complicated. You must use vt.url_id() for generating the appropriate identifier. You can find more information about why this is necessary in: - https://docs.virustotal.com/reference/url.

Also notice how we are using a placeholder {} in the path. The placeholder will be replaced with the value of url_id. This works exactly like Python's new−style string formatting using the .format() function. This other code is equivalent:

>>> url = client.get_object("/urls/{}".format(url_id))

The returned object contains the URL attributes. Some examples:

>>> url.times_submitted
213730

>>> url.last_analysis_stats
{'harmless': 61, 'malicious': 0, 'suspicious': 1, 'timeout': 0, 'undetected': 8}

Scan a file

Before scanning a file is highly recommended that you look up for it as described in Get information about a file. If the file already exists and the latest analysis is fresh enough, you can use that instead of scanning the file again. If not, you can scan it with:

>>> with open("/path/to/file", "rb") as f:
>>> analysis = client.scan_file(f)

When vt.Client.scan_file() returns the analysis is not completed yet, the object returned only has the analysis ID but not attributes. In order to track the status of the analysis you must ask for the analysis object until it's status is completed:

>>> while True:
>>> analysis = client.get_object("/analyses/{}", analysis.id)
>>> print(analysis.status)
>>> if analysis.status == "completed":
>>> break
>>> time.sleep(30)

Alternatively you can use the wait_for_completion argument:

>>> with open("/path/to/file", "rb") as f:
>>> analysis = client.scan_file(f, wait_for_completion=True)

When wait_for_completion is True vt.Client.scan_file() doesn't return until the analysis has been completed.

Scan an URL

Scanning a URL is very similar to scanning a file, you just need to use vt.Client.scan_url() instead of vt.Client.scan_file():

>>> analysis = client.scan_url('https://somedomain.com/foo/bar')

Download a file

NOTE:

This feature is available only for premium users.

Downloading a file it's very simple, you only need to provide the hash and a file−like object where the file's content will be written to. The target file must be opened in "wb" mode:

>>> with open("/path/to/target_file", "wb") as f:
>>> client.download_file("44d88612fea8a8f36de82e1278abb02f", f)

Start and abort a Retrohunt job

NOTE:

This feature is available only for premium users.

Create an empty object of type retrohunt_job and set its rules attribute:

>>> job = vt.Object("retrohunt_job")
>>> job.rules = "rule test { condition:false }"

Post the object to the /intelligence/retrohunt_jobs collection:

>>> job = client.post_object("/intelligence/retrohunt_jobs", obj=job)

Notice that job has been replaced with the value returned by vt.Client.post_object(), so now job has an ID and additional attributes.

>>> job.id
'username−123456789'

>>> job.status
'starting'

With the object identifier you can ask for the job again a see it making progress. Wait for a few seconds and do:

>>> job = client.get_object("/intelligence/retrohunt_jobs/{}", job.id)

The job status should have changed to running:

>>> job.status
'running'

And the progress attribute should show the completion percentage:

>>> job.progress
1.4145595

Let's abort the job:

>>> response = client.post("/intelligence/retrohunt_jobs/{}/abort", job.id)
>>> response.status
200

Here we are using vt.Client.post() instead of vt.Client.post_object(), this is because the /intelligence/retrohunt_jobs/{id}/abort endpoint doesn't expect an object, just a POST request with an empty body. The result from vt.Client.post() is a vt.ClientResponse instance.

Create a LiveHunt ruleset

NOTE:

This feature is available only for premium users.

Create an empty object of type hunting_ruleset and set its name and rules attributes:

>>> rs = vt.Object("hunting_ruleset")
>>> rs.name = "My test ruleset"
>>> rs.rules = "rule test { condition:false }"

Post the object to the /intelligence/hunting_rulesets collection:

>>> rs = client.post_object("/intelligence/hunting_rulesets", obj=rs)

Because we didn't set the enabled attribute while creating the ruleset, it was created with enabled=False by default:

>>> rs.enabled
False

Let's enable the ruleset:

>>> rs.enabled = True
>>> rs = client.patch_object("/intelligence/hunting_rulesets/{}", rs.id, obj=rs)
>>> rs.enabled
True

Closing

Once you're done using the client, call client.close() at the end of your script, to make sure the client is properly closed. Otherwise you might see tracebacks indicating the client was never closed.

>>> client.close()

If you use a context manager<https://docs.python.org/3/reference/datamodel.html#context−managers>, the client is automatically closed after exiting, so there's no need to call close:

>>> with vt.Client('<apikey>') as client:
... file = client.get_object("/files/44d88612fea8a8f36de82e1278abb02f")
... print(file.type_tag)
text

API REFERENCE

Client

VT module.
exception vt.APIError(code: str, message: str)

Class that encapsules errors returned by the VirusTotal API.

class vt.Client(apikey: str, agent: str = 'unknown', host: str | None =
None, trust_env: bool = False, timeout: int = 300, proxy: str | None =
None, headers: Dict | None = None, verify_ssl: bool = True, connector:
BaseConnector = None)

Client for interacting with VirusTotal.
Parameters

apikey (str) −− Your VirusTotal API key.

agent (str) −− A string that identifies your application.

host (str) −− By default https://www.virustotal.com, it can be changed for testing purposes.

trust_env (bool) −− Get proxies information from HTTP_PROXY/HTTPS_PROXY environment variables if the parameter is True (False by default).

timeout (int) −− A int that determines the number of seconds to wait for a request to timeout (300 by default).

proxy (str) −− A string indicating the proxy to use for requests made by the client (None by default).

headers (dict) −− Dict of headers defined by the user.

verify_ssl (bool) −− Whether to verify the certificate in SSL connections.

connector (aiohttp.BaseConnector) −− (Optional) A custom aiohttp connector.

close() -> None

Closes the client.

When the client is not needed anymore it must be closed for releasing resources like TCP connections.

Not closing the client after it's used might show error tracebacks indicating it was not properly closed.

async close_async() -> None

Like close() but returns a coroutine.

delete(path: str, *path_args: Any, data: str | bytes | None =
None, json_data: Dict | None = None) ->
ClientResponse

Sends a DELETE request to a given API endpoint.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

data (A string or bytes) −− Data sent in the request body.

json_data (dict) −− dict containing data to send in the request body as JSON.

Returns

An instance of ClientResponse.

async delete_async(path: str, *path_args: Any, data: str | bytes
| None = None, json_data: Dict | None = None) ->
ClientResponse

Like delete() but returns a coroutine.

download_file(file_hash: str, file: BinaryIO) -> None

Downloads a file given its _ (SHA−256, SHA−1 or MD5).

The file identified by the hash will be written to the provided file object. The file object must be opened in write binary mode ('wb').
Parameters

file_hash (str) −− File hash.

file (file−like object) −− A file object where the downloaded file will be written to.

async download_file_async(file_hash: str, file: BinaryIO) ->
None

Like download_file() but returns a coroutine.

download_zip_files(hashes: List[str], zipfile: BinaryIO,
password: str | None = None, sleep_time: int = 20) -> None

Creates a bundle zip bundle containing one or multiple files.

The file identified by the hash will be written to the provided file object. The file object must be opened in write binary mode ('wb').
Parameters

hashes −− list of file hashes (SHA−256, SHA−1 or MD5).

zipfile −− A file object where the downloaded zip file will be written to.

password −− optional, a password to protect the zip file.

sleep_time −− optional, seconds to sleep between each request.

feed(feed_type: FeedType, cursor: str | None = None) -> Feed

Returns an iterator for a VirusTotal feed.

This functions returns an iterator that allows to retrieve a continuous stream of files as they are scanned by VirusTotal. See the documentation for the Feed class for more details.
Parameters

feed_type −− One of the supported feed types enumerated in FeedType.

cursor (str) −− An optional cursor indicating where to start. This argument can be a string in the format 'YYYMMDDhhmm' indicating the date and time of the first package that will be retrieved.

get(path: str, *path_args: Any, params: Dict | None = None) ->
ClientResponse

Sends a GET request to a given API endpoint.

This is a low−level function that returns a raw HTTP response, no error checking nor response parsing is performed. See get_json(), get_data() and get_object() for higher−level functions.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

params (dict) −− Parameters sent in the request.

Returns

An instance of ClientResponse.

async get_async(path: str, *path_args: Any, params: Dict | None
= None) ->
ClientResponse

Like get() but returns a coroutine.

get_data(path: str, *path_args: Any, params: Dict | None = None)
-> Any

Sends a GET request to a given API endpoint and returns response's data.

Most VirusTotal API responses are JSON−encoded with the following format:

{"data": <response data>}

This function parses the server's response and return only the data, if the response is not in the expected format an exception is raised. For endpoints where the data is a VirusTotal object you can use get_object() instead.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

params (dict) −− Parameters sent in the request.

Returns

Whatever the server returned in the response's data field, it may be a dict, list, string or some other Python type, depending on the endpoint called.

async get_data_async(path: str, *path_args: Any, params: Dict |
None = None) -> Any

Like get_data() but returns a coroutine.

async get_error_async(response: ClientResponse) -> APIError |
None

Given a ClientResponse returns a APIError

This function checks if the response from the VirusTotal backend was an error and returns the appropriate APIError or None if no error occurred.
Parameters

response −− A ClientResponse instance.

Returns

An instance of APIError or None.

get_json(path: str, *path_args: Any, params: Dict | None = None)
-> Dict

Sends a GET request to a given API endpoint and parses the response.

Most VirusTotal API responses are JSON−encoded. This function parses the JSON, check for errors, and return the server response as a dictionary.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

params (dict) −− Parameters sent in the request.

Returns

A dictionary with the backend's response.

async get_json_async(path: str, *path_args: Any, params: Dict |
None = None) -> Dict

Like get_json() but returns a coroutine.

get_object(path: str, *path_args: Any, params: Dict | None =
None) -> Object

Sends a GET request to a given API endpoint and returns an object.

The endpoint specified must return an object, not a collection. This means that get_object can be used with endpoints like /files/{file_id} and /urls/{url_id}, which return an individual object but not with /comments, which returns a collection of objects.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

params (dict) −− Parameters sent in the request.

Returns

An instance of Object.

async get_object_async(path: str, *path_args: Any, params: Dict
| None = None) -> Object

Like get_object() but returns a coroutine.

iterator(path: str, *path_args: Any, params: Dict | None = None,
cursor: str | None = None, limit: int | None = None, batch_size:
int = 0) -> Iterator

Returns an iterator for the collection specified by the given path.

The endpoint specified by path must return a collection of objects. An example of such an endpoint are /comments and /intelligence/search.
Parameters

path (str) −− Path to API endpoint returning a collection.

path_args −− A variable number of arguments that are put into any placeholders used in path.

params (dict) −− Additional parameters passed to the endpoint.

cursor (str) −− Cursor for resuming the iteration at the point it was left previously. A cursor can be obtained with Iterator.cursor(). This cursor is not the same one returned by the VirusTotal API.

limit (int) −− Maximum number of objects that will be returned by the iterator. If a limit is not provided the iterator continues until it reaches the last object in the collection.

batch_size (int) −− Maximum number of objects retrieved on each call to the endpoint. If not provided the server will decide how many objects to return.

Returns

An instance of Iterator.

patch(path: str, *path_args: Any, data: str | bytes | None =
None, json_data: Dict | None = None) ->
ClientResponse

Sends a PATCH request to a given API endpoint.

This is a low−level function that returns a raw HTTP response, no error checking nor response parsing is performed. See patch_object() for a higher−level function.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

data (A string or bytes) −− Data sent in the request body.

json_data (dict) −− dict containing data to send in the request body as JSON.

Returns

An instance of ClientResponse.

async patch_async(path: str, *path_args: Any, data: str | bytes
| None = None, json_data: Dict | None = None) ->
ClientResponse

Like patch() but returns a coroutine.

patch_object(path: str, *path_args: Any, obj: Object) -> Object

Sends a PATCH request for modifying an object.

This function modifies an object. The endpoint must be one that identifies an object, like /intelligence/hunting_rulesets/{id}.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

obj (Object) −− Object that has been modified.

Returns

An instance of Object representing the same object after the changes has been applied.

async patch_object_async(path: str, *path_args: Any, obj:
Object) -> Object

Like patch_object() but returns a coroutine.

post(path: str, *path_args: Any, data: str | bytes | None =
None, json_data: Dict | None = None) ->
ClientResponse

Sends a POST request to a given API endpoint.

This is a low−level function that returns a raw HTTP response, no error checking nor response parsing is performed. See post_object() for a higher−level function.
Parameters

path (str) −− Path to API endpoint, can contain format placeholders {}.

path_args −− A variable number of arguments that are put into any placeholders used in path.

data (A string or bytes) −− Data sent in the request body.

json_data (dict) −− dict containing data to send in the request body as JSON.

Returns

An instance of ClientResponse.

async post_async(path: str, *path_args: Any, data: str | bytes |
None = None, json_data: Dict | None = None) ->
ClientResponse

Like post() but returns a coroutine.

post_object(path: str, *path_args: Any, obj: Object) -> Object

Sends a POST request for creating an object.

This function create a new object. The endpoint must be one that identifies a collection, like /intelligence/hunting_rulesets.
Parameters

path (str) −− Path to API endpoint.

path_args −− A variable number of arguments that are put into any placeholders used in path.

obj (Object) −− Instance Object with the type expected by the API endpoint.

Returns

An instance of Object representing the new object.

async post_object_async(path: str, *path_args: Any, obj: Object)
-> Object

Like post_object() but returns a coroutine.

scan_file(file: BinaryIO, wait_for_completion: bool = False) ->
Object

Scans a file.
Parameters

file (File−like object.) −− File to be scanned.

wait_for_completion (bool) −− If True the function doesn't return until the analysis has been completed.

Returns

An instance of Object of analysis type.

async scan_file_async(file: BinaryIO, wait_for_completion: bool
= False) -> Object

Like scan_file() but returns a coroutine.

scan_file_private(file: BinaryIO | str, wait_for_completion:
bool = False) -> Object

Scan file privately.

Args:

file: File to scan (path string or file object) wait_for_completion: Wait for completion

Returns:

Object: Analysis object with scan results

async scan_file_private_async(file: BinaryIO | str,
wait_for_completion: bool = False) -> Object

Async version of scan_file_private

scan_url(url: str, wait_for_completion: bool = False) -> Object

Scans a URL.
Parameters

url (str) −− The URL to be scanned.

wait_for_completion (bool) −− If True the function doesn't return until the analysis has been completed.

Returns

An instance of Object of analysis type.

async scan_url_async(url: str, wait_for_completion: bool =
False) -> Object

Like scan_url() but returns a coroutine.

scan_url_private(url: str, wait_for_completion: bool = False) ->
Object

Scans a URL privately.
Parameters

url (str) −− The URL to be scanned.

wait_for_completion (bool) −− If True the function doesn't return until the analysis has been completed.

Returns

An instance of Object of analysis type.

async scan_url_private_async(url: str, wait_for_completion: bool
= False) -> Object

Like scan_url_private() but returns a coroutine.

class vt.ClientResponse(aiohttp_resp: ClientResponse)

Class representing the HTTP responses returned by the client.

This class is just a thing wrapper around aiohttp.ClientResponse that allows using it in both asynchronous and synchronous mode. Instances of this class have all the attributes that you can find in aiohttp.ClientResponse, like version, status, method, url, and so on. Methods in aiohttp.ClientResponse that return a coroutine have two flavors in this class: synchronous and asynchronous. For example, aiohttp.ClientResponse.read() becomes vt.ClientResponse.read_async(), and vt.ClientResponse.read() is the synchronous version of vt.ClientResponse.read_async(). Find more information about attributes and methods in aiohttp.ClientResponse in:

- https://aiohttp.readthedocs.io/en/stable/client_reference.html#aiohttp.ClientResponse

Feed

NOTE:

This feature is available only for premium users.

VT module.
class vt.Feed(client:
Client, feed_type: FeedType, cursor: str | None =
None)

Feed represents a stream of objects received from VirusTotal in real−time.

For more information about VirusTotal Feeds see: - https://docs.virustotal.com/reference/file−feed

In the example below the loop iterates forever, retrieving file objects as they are processed by VirusTotal. For a more elaborate example see the file examples/file_feed.py in this repository.

>>> with vt.Client(<apikey>) as client:
>>> for file_obj in client.feed(vt.FeedType.FILES):
>>> print(file_obj.id)

Instances of this class are not created directly, you should use the vt.Client.feed() method instead.
property cursor: str

Returns a cursor indicating the last item retrieved from the feed.

This cursor can be used for creating a new Feed object that continues where a previous one left.

class vt.FeedType(*values)

Feed types.
FILES = 'files'
FILE_BEHAVIOURS = 'file−behaviours'
URLS = 'urls'

Object

VT module.
class vt.Object(obj_type: str, obj_id: str | None = None,
obj_attributes: Dict | None = None)

This class encapsulates any type of object in the VirusTotal API.

Instances of this class are usually obtained from calls to vt.Client.get_object(), however, you need to instantiante this class yourself for creating new objects that will be sent to the backend in a call to vt.Client.post_object().

Learn more about objects in the VirusTotal API in: - https://docs.virustotal.com/reference/objects
classmethod from_dict(obj_dict: Dict)

Creates an object from its dictionary representation.

The dictionary representation of a VirusTotal API object has the following structure:

{
"type": <object type>,
"id": <object id>,
"links": {
"self": "https://www.virustotal.com/api/v3/<collection name>/<obj id>"
},
"attributes": {
...
}
}

At least type and id are required to be present in the dictionary, if not, an exception is raised.

get(attr_name: str, default: Any | None = None) -> Any

Returns an attribute by name.

If the attribute is not present in the object, it returns None or the value specified in the "default" argument.
Parameters

attr_name (str) −− Name of the attribute.

default −− An optional value that will be returned if the attribute is not present in the object.

set_data(key: str, value: Any)

Sets a field of the object's data.

Iterator

VT module.
class vt.Iterator(client:
Client, path: str, params=None, cursor: str |
None = None, limit: int | None = None, batch_size: int = 0)

Iterator allows iterating over object collections.

Some endpoints in the VirusTotal API represent a collection of objects, for example:

/files/{id}/comments

/intelligence/search

These collections can be iterated using an instance of this class.

Learn more about collections in the VirusTotal API in: - https://docs.virustotal.com/reference/collections−create

The following example iterates over the most recent 200 comments, retrieving them in batches of 20:

>>> client = vt.Client(<apikey>)
>>> it = client.iterator('/comments', batch_size=20, limit=200)
>>> for comment in it:
>>> print(comment.text)
>>> print(it.cursor)

When the iteration is done, it print the iterator's cursor. The cursor can be used for creating another iterator that continues at the point where the previous iterator left.

The Iterator class also exposes an async iterator:

>>> # Define an async coroutine that iterates over the comments.
>>> async def print_comments():
>>> async for comment in client.iterator('/comments', limit=200):
>>> print(comment.id)
>>> # Run the print_comments coroutine using asyncio
>>> import asyncio
>>> asyncio.get_event_loop().run_until_complete(print_comments)
property cursor: str | None

Cursor indicating the last returned object.

This cursor can be used for creating a new iterator that continues where the current one left.

property meta_async: Dict

Meta information.

The cursor is not included, as it's exposed as a property.

Utility functions

VT module.
vt.url_id(url: str) -> str

Generates the object ID for an URL.

The ID generated by this function can be used in calls that expect a URL ID like client.get_object('/urls/<id>')

AUTHOR

VirusTotal

COPYRIGHT

2023, VirusTotal


Updated 2026-06-01 - jenkler.se | uex.se