# VirusTotal

> Check files, URLs, domains and IP addresses with VirusTotal's seventy-odd antivirus engines and blocklists: get reports and verdicts, scan files and links, trace passive DNS, subdomains and the files that contact a domain or address, see what a file did in VirusTotal's sandboxes, and comment and vote with its security community.

App · Compliance & Security · 19 actions. Web page: https://docs.lodol.com/docs/integrations/virustotal

## Actions

### Add comment

Post a comment on a file, URL, domain or IP address for VirusTotal's community to see. Words starting with # become its tags.

**Inputs**

- What it is (`item_type`, text, required): Whether the item is a file (given by its hash), a URL, a domain or an IP address. One of: `file` (File (by its hash)), `url`, `domain`, `ip_address` (IP address).
- Item (`item`, text, required): The file's MD5, SHA-1 or SHA-256 hash, the URL, the domain or the IP address.
- Comment (`text`, text, required): What to say. Comments are public, so leave out names, email addresses and anything else personal.

**Outputs**

- `comment_id` (text): The comment's ID, for Delete comment
- `item` (text): The item: a file hash, URL, domain or IP address
- `item_type` (text): What the item is: file, url, domain or ip_address
- `posted_at` (text): When it was posted (ISO 8601)
- `tags` (list): The #tags in it, without the #
- `text` (text): What it says

**Example output**

```json
{
  "comment_id": "d-example.com-5f1c0a9e",
  "item": "example.com",
  "item_type": "domain",
  "posted_at": "2026-09-30T09:00:00+00:00",
  "tags": [
    "phishing"
  ],
  "text": "Seen in a phishing email posing as a bank. #phishing"
}
```

### Add vote

Vote a file, URL, domain or IP address harmless or malicious. Voting the same way twice comes back with 'voted' false instead of stopping the run.

**Inputs**

- What it is (`item_type`, text, required): Whether the item is a file (given by its hash), a URL, a domain or an IP address. One of: `file` (File (by its hash)), `url`, `domain`, `ip_address` (IP address).
- Item (`item`, text, required): The file's MD5, SHA-1 or SHA-256 hash, the URL, the domain or the IP address.
- Vote (`verdict`, text, required): Whether you think it is harmless or malicious. One of: `harmless`, `malicious`.

**Outputs**

- `item` (text): The item: a file hash, URL, domain or IP address
- `item_type` (text): What the item is: file, url, domain or ip_address
- `verdict` (text): The vote
- `voted` (true/false): True when the vote was cast. False when you had already voted it the same way
- `voted_at` (text): When (ISO 8601). Empty when not voted

**Example output**

```json
{
  "item": "example.com",
  "item_type": "domain",
  "verdict": "harmless",
  "voted": true,
  "voted_at": "2026-09-30T09:00:00+00:00"
}
```

### Delete comment

Delete one of your own comments. A comment that is already gone comes back with 'deleted' false instead of stopping the run.

**Inputs**

- Comment ID (`comment_id`, text, required): The comment_id Add comment or List comments returned.

**Outputs**

- `comment_id` (text): The comment
- `deleted` (true/false): False when there was no such comment to delete

**Example output**

```json
{
  "comment_id": "d-example.com-5f1c0a9e",
  "deleted": true
}
```

### Get analysis

See where a scan stands, and its verdict once every engine has answered. Use it for a scan that was still running when its step stopped waiting.

**Inputs**

- Analysis ID (`analysis_id`, text, required): The analysis_id a scan or rescan step returned.
- Seconds to wait for the verdict (`wait_seconds`, number): How long to wait for a scan still running to finish, up to 300. With 0 the scan is read once, as it stands. From 0 to 300. Default: `0`.

**Outputs**

- `analysis_id` (text): The scan's ID, for Get analysis
- `analyzed_at` (text): When the scan started (ISO 8601)
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `finished` (true/false): True once every engine has answered. Until then the verdict is unknown and Get analysis reads it later
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `harmless` (number): How many security vendors say it is harmless
- `item` (text): The file's SHA-256 or the URL scanned
- `item_type` (text): file or url when the scan says which; empty otherwise
- `link` (text): The scanned item's page on VirusTotal
- `malicious` (number): How many security vendors flag it as malicious
- `status` (text): queued, in-progress or completed
- `suspicious` (number): How many security vendors flag it as suspicious
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet

**Example output**

```json
{
  "analysis_id": "NDRkODg2MTJmZWE4YThmMzZkZTgyZTEyNzhhYmIwMmY6MTc5MTE5NjM2NA==",
  "analyzed_at": "2026-09-30T08:12:44+00:00",
  "engine_count": 67,
  "finished": true,
  "flagged_by": [
    {
      "category": "malicious",
      "engine": "BitDefender",
      "result": "EICAR-Test-File (not a virus)"
    },
    {
      "category": "malicious",
      "engine": "Kaspersky",
      "result": "EICAR-Test-File"
    }
  ],
  "harmless": 0,
  "item": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "item_type": "file",
  "link": "https://www.virustotal.com/gui/file/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "malicious": 62,
  "status": "completed",
  "suspicious": 0,
  "undetected": 5,
  "verdict": "malicious"
}
```

### Get API quota

See how many requests the connected VirusTotal account has used today, this hour and this month, and how many it has left, before a run that makes many.

**Inputs**: None.

**Outputs**

- `daily_limit` (number): Requests allowed a day: 500 on the free API
- `daily_reset_at` (text): When the daily allowance resets: the next 00:00 UTC
- `hourly_limit` (number): Requests allowed an hour
- `monthly_limit` (number): Requests allowed a month
- `requests_left_this_month` (number): Requests left this month
- `requests_left_today` (number): Requests left today
- `requests_this_hour` (number): Requests made this hour
- `requests_this_month` (number): Requests made this month
- `requests_today` (number): Requests made today (UTC)
- `user` (text): The account's user name

**Example output**

```json
{
  "daily_limit": 500,
  "daily_reset_at": "2026-10-01T00:00:00+00:00",
  "hourly_limit": 240,
  "monthly_limit": 15500,
  "requests_left_this_month": 14020,
  "requests_left_today": 463,
  "requests_this_hour": 12,
  "requests_this_month": 1480,
  "requests_today": 37,
  "user": "lodol-security"
}
```

### Get DNS resolutions

Passive DNS: the IP addresses a domain has pointed to, or the domains that have pointed to an IP address, newest first, with how many vendors flag each.

**Inputs**

- Domain or IP address (`domain_or_ip`, text, required): A domain, like example.com, or an IPv4 or IPv6 address.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `count` (number): How many came back on this page
- `has_more` (true/false): True when there are more on later pages
- `item` (text): The domain or IP address
- `item_type` (text): domain or ip_address
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page
- `resolutions` (list): The resolutions, newest first

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "item": "example.com",
  "item_type": "domain",
  "next_cursor": "",
  "resolutions": [
    {
      "domain": "example.com",
      "domain_malicious": 0,
      "ip_address": "23.215.0.136",
      "ip_address_malicious": 0,
      "resolved_at": "2026-09-28T02:11:40+00:00"
    }
  ]
}
```

### Get domain report

Look up a domain: how many security vendors flag it, what they categorise it as, its registrar and age, and its current DNS records.

**Inputs**

- Domain (`domain`, text, required): The domain, like example.com. A URL or email address works too: its domain is looked up.

**Outputs**

- `categories` (list): What security vendors say it is, e.g. search engines or phishing
- `created_at` (text): When it was registered (ISO 8601)
- `dns_records` (list): Its DNS records when VirusTotal last looked
- `domain` (text): The domain
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `expires_at` (text): When its registration runs out (ISO 8601)
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `found` (true/false): False when VirusTotal has never seen it. Everything else is then empty and the verdict is unknown
- `harmless` (number): How many security vendors say it is harmless
- `last_analyzed_at` (text): When it was last scanned (ISO 8601)
- `link` (text): Its page on VirusTotal. Empty when VirusTotal has never seen it
- `malicious` (number): How many security vendors flag it as malicious
- `registrar` (text): Who it is registered with
- `reputation` (number): VirusTotal's community score: below 0 leans malicious, above 0 harmless. Empty when unknown
- `suspicious` (number): How many security vendors flag it as suspicious
- `tags` (list): VirusTotal's tags for it
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet
- `votes_harmless` (number): How many community members voted it harmless
- `votes_malicious` (number): How many community members voted it malicious

**Example output**

```json
{
  "categories": [
    "information technology",
    "reference"
  ],
  "created_at": "1995-08-14T04:00:00+00:00",
  "dns_records": [
    {
      "ttl": 300,
      "type": "A",
      "value": "23.215.0.136"
    },
    {
      "ttl": 300,
      "type": "AAAA",
      "value": "2600:1406:3a00:21::173e:2e65"
    }
  ],
  "domain": "example.com",
  "engine_count": 93,
  "expires_at": "2027-08-13T04:00:00+00:00",
  "flagged_by": [],
  "found": true,
  "harmless": 67,
  "last_analyzed_at": "2026-09-29T11:17:32+00:00",
  "link": "https://www.virustotal.com/gui/domain/example.com",
  "malicious": 0,
  "registrar": "RESERVED-Internet Assigned Numbers Authority",
  "reputation": 0,
  "suspicious": 0,
  "tags": [],
  "undetected": 26,
  "verdict": "clean",
  "votes_harmless": 5,
  "votes_malicious": 0
}
```

### Get file behaviour

See what a file did when VirusTotal's sandboxes ran it: the MITRE ATT&CK techniques it showed, the domains it looked up, the addresses and URLs it contacted, the processes and commands it ran, and the files and registry keys it changed. VirusTotal lists sandbox data among its premium features, so a free key may be refused.

**Inputs**

- File hash (`file_hash`, text, required): The file's MD5, SHA-1 or SHA-256 hash, or a link to its page on VirusTotal.

**Outputs**

- `commands_executed` (list): Shell commands it ran
- `dns_lookups` (list): Domains it looked up
- `file_hash` (text): The file asked about
- `files_deleted` (list): Files it deleted
- `files_dropped` (list): Files it dropped
- `files_written` (list): Files it wrote to
- `found` (true/false): False when no sandbox has run the file
- `http_requests` (list): HTTP requests it made
- `ip_traffic` (list): Addresses it contacted
- `link` (text): The file's behaviour page on VirusTotal
- `mitre_attack_techniques` (list): MITRE ATT&CK techniques seen
- `mutexes_created` (list): Mutexes it created
- `processes_created` (list): Processes it started
- `registry_keys_set` (list): Windows registry keys it set
- `tags` (list): Behaviour tags, e.g. DETECT_DEBUG_ENVIRONMENT
- `verdicts` (list): What the sandboxes judged it, e.g. MALWARE

**Example output**

```json
{
  "commands_executed": [
    "cmd.exe /c schtasks /create /tn Updater"
  ],
  "dns_lookups": [
    {
      "hostname": "update.example.net",
      "resolved_ips": [
        "203.0.113.7"
      ]
    }
  ],
  "file_hash": "e7a2b1f0c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c",
  "files_deleted": [],
  "files_dropped": [
    {
      "path": "C:\\Users\\user\\AppData\\Roaming\\updater.dll",
      "sha256": "4752a1781840cbb27557eaf48dd69fee02d4590df4ab63d4243bdf98cab419c9"
    }
  ],
  "files_written": [
    "C:\\Users\\user\\AppData\\Roaming\\updater.dll"
  ],
  "found": true,
  "http_requests": [
    {
      "method": "POST",
      "status_code": 200,
      "url": "http://update.example.net/gate.php"
    }
  ],
  "ip_traffic": [
    {
      "destination_ip": "203.0.113.7",
      "destination_port": 443,
      "protocol": "TCP"
    }
  ],
  "link": "https://www.virustotal.com/gui/file/e7a2b1f0c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c/behavior",
  "mitre_attack_techniques": [
    {
      "description": "Adds itself to a Run key to start with Windows",
      "id": "T1547.001",
      "severity": "high"
    }
  ],
  "mutexes_created": [
    "Global\\UpdaterMutex"
  ],
  "processes_created": [
    "C:\\Users\\user\\AppData\\Local\\Temp\\invoice.exe"
  ],
  "registry_keys_set": [
    {
      "key": "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\Updater",
      "value": "C:\\Users\\user\\AppData\\Roaming\\updater.dll"
    }
  ],
  "tags": [
    "DETECT_DEBUG_ENVIRONMENT",
    "PERSISTENCE"
  ],
  "verdicts": [
    "MALWARE"
  ]
}
```

### Get file report

Look up a file by its hash: how many of some seventy security vendors flag it and what they call it, its threat label, names, size and type, and when VirusTotal first saw it. A file VirusTotal has never seen is an answer, not an error: 'found' is false and the verdict unknown.

**Inputs**

- File hash (`file_hash`, text, required): The file's MD5, SHA-1 or SHA-256 hash, or a link to its page on VirusTotal.

**Outputs**

- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `first_submitted_at` (text): When VirusTotal first saw it (ISO 8601)
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `found` (true/false): False when VirusTotal has never seen it. Everything else is then empty and the verdict is unknown
- `harmless` (number): How many security vendors say it is harmless
- `last_analyzed_at` (text): When it was last scanned (ISO 8601)
- `last_submitted_at` (text): When it was last sent to VirusTotal (ISO 8601)
- `link` (text): Its page on VirusTotal. Empty when VirusTotal has never seen it
- `malicious` (number): How many security vendors flag it as malicious
- `md5` (text): The file's MD5 hash
- `name` (text): The file's most telling name
- `names` (list): Names it was sent to VirusTotal under
- `reputation` (number): VirusTotal's community score: below 0 leans malicious, above 0 harmless. Empty when unknown
- `sha1` (text): The file's SHA-1 hash
- `sha256` (text): The file's SHA-256 hash
- `size` (number): Its size in bytes
- `suspicious` (number): How many security vendors flag it as suspicious
- `tags` (list): VirusTotal's tags for it
- `threat_categories` (list): What kind of threat it is, e.g. trojan or ransomware
- `threat_label` (text): VirusTotal's name for the threat, drawn from the vendors' names, e.g. trojan.emotet/zusy
- `threat_names` (list): The threat family names vendors use, e.g. emotet
- `times_submitted` (number): How many times it was sent to VirusTotal
- `type` (text): What kind of file it is, e.g. Win32 EXE or PDF
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet
- `votes_harmless` (number): How many community members voted it harmless
- `votes_malicious` (number): How many community members voted it malicious

**Example output**

```json
{
  "engine_count": 67,
  "first_submitted_at": "2006-05-22T07:43:56+00:00",
  "flagged_by": [
    {
      "category": "malicious",
      "engine": "BitDefender",
      "result": "EICAR-Test-File (not a virus)"
    },
    {
      "category": "malicious",
      "engine": "Kaspersky",
      "result": "EICAR-Test-File"
    }
  ],
  "found": true,
  "harmless": 0,
  "last_analyzed_at": "2026-09-30T08:12:44+00:00",
  "last_submitted_at": "2026-09-30T08:12:44+00:00",
  "link": "https://www.virustotal.com/gui/file/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "malicious": 62,
  "md5": "44d88612fea8a8f36de82e1278abb02f",
  "name": "eicar.com",
  "names": [
    "eicar.com",
    "eicar.txt"
  ],
  "reputation": 3000,
  "sha1": "3395856ce81f2b7382dee72602f798b642f14140",
  "sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "size": 68,
  "suspicious": 0,
  "tags": [
    "text",
    "attachment",
    "known-distributor"
  ],
  "threat_categories": [
    "virus",
    "trojan"
  ],
  "threat_label": "virus.eicar/test",
  "threat_names": [
    "eicar",
    "test"
  ],
  "times_submitted": 1500000,
  "type": "Text",
  "undetected": 5,
  "verdict": "malicious",
  "votes_harmless": 2800,
  "votes_malicious": 1200
}
```

### Get IP address report

Look up an IP address: how many security vendors flag it, and who runs it (network, autonomous system and country).

**Inputs**

- IP address (`ip_address`, text, required): The IPv4 or IPv6 address to look up.

**Outputs**

- `as_owner` (text): Who runs that autonomous system
- `asn` (number): The number of the autonomous system it is in
- `continent` (text): Two-letter code of its continent, e.g. NA
- `country` (text): Two-letter code of the country it is in, e.g. US
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `found` (true/false): False when VirusTotal has never seen it. Everything else is then empty and the verdict is unknown
- `harmless` (number): How many security vendors say it is harmless
- `ip_address` (text): The address
- `last_analyzed_at` (text): When it was last scanned (ISO 8601)
- `link` (text): Its page on VirusTotal. Empty when VirusTotal has never seen it
- `malicious` (number): How many security vendors flag it as malicious
- `network` (text): The network it belongs to, e.g. 8.8.8.0/24
- `regional_internet_registry` (text): The registry that assigned it, e.g. ARIN or RIPE NCC
- `reputation` (number): VirusTotal's community score: below 0 leans malicious, above 0 harmless. Empty when unknown
- `suspicious` (number): How many security vendors flag it as suspicious
- `tags` (list): VirusTotal's tags for it
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet
- `votes_harmless` (number): How many community members voted it harmless
- `votes_malicious` (number): How many community members voted it malicious

**Example output**

```json
{
  "as_owner": "GOOGLE",
  "asn": 15169,
  "continent": "NA",
  "country": "US",
  "engine_count": 93,
  "flagged_by": [],
  "found": true,
  "harmless": 63,
  "ip_address": "8.8.8.8",
  "last_analyzed_at": "2026-09-29T20:05:08+00:00",
  "link": "https://www.virustotal.com/gui/ip-address/8.8.8.8",
  "malicious": 0,
  "network": "8.8.8.0/24",
  "regional_internet_registry": "ARIN",
  "reputation": 523,
  "suspicious": 0,
  "tags": [],
  "undetected": 30,
  "verdict": "clean",
  "votes_harmless": 220,
  "votes_malicious": 30
}
```

### Get URL report

Look up a URL: how many security vendors flag it as phishing or malware, what they categorise it as, its page title and where it ends up after redirects. A URL VirusTotal has never scanned is an answer, not an error: 'found' is false.

**Inputs**

- URL (`url`, text, required): The URL to look up, like https://example.com/page, or the url_id a scan or report returned.

**Outputs**

- `categories` (list): What security vendors say it is, e.g. search engines or phishing
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `final_url` (text): Where the URL ended up after redirects
- `first_submitted_at` (text): When VirusTotal first saw it (ISO 8601)
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `found` (true/false): False when VirusTotal has never seen it. Everything else is then empty and the verdict is unknown
- `harmless` (number): How many security vendors say it is harmless
- `http_status` (number): The HTTP status the page answered with
- `last_analyzed_at` (text): When it was last scanned (ISO 8601)
- `link` (text): Its page on VirusTotal. Empty when VirusTotal has never seen it
- `malicious` (number): How many security vendors flag it as malicious
- `reputation` (number): VirusTotal's community score: below 0 leans malicious, above 0 harmless. Empty when unknown
- `suspicious` (number): How many security vendors flag it as suspicious
- `tags` (list): VirusTotal's tags for it
- `threat_names` (list): Threats found on the page
- `times_submitted` (number): How many times it was sent to VirusTotal
- `title` (text): The page's title
- `undetected` (number): How many security vendors checked it and found nothing
- `url` (text): The URL
- `url_id` (text): VirusTotal's ID for the URL
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet
- `votes_harmless` (number): How many community members voted it harmless
- `votes_malicious` (number): How many community members voted it malicious

**Example output**

```json
{
  "categories": [
    "information technology",
    "reference"
  ],
  "engine_count": 92,
  "final_url": "https://example.com/",
  "first_submitted_at": "2013-03-09T17:49:48+00:00",
  "flagged_by": [],
  "found": true,
  "harmless": 68,
  "http_status": 200,
  "last_analyzed_at": "2026-09-29T21:04:16+00:00",
  "link": "https://www.virustotal.com/gui/url/0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7",
  "malicious": 0,
  "reputation": 0,
  "suspicious": 0,
  "tags": [],
  "threat_names": [],
  "times_submitted": 4200,
  "title": "Example Domain",
  "undetected": 24,
  "url": "https://example.com/",
  "url_id": "0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7",
  "verdict": "clean",
  "votes_harmless": 3,
  "votes_malicious": 0
}
```

### List comments

Get what VirusTotal's community wrote about a file, URL, domain or IP address, newest first.

**Inputs**

- What it is (`item_type`, text, required): Whether the item is a file (given by its hash), a URL, a domain or an IP address. One of: `file` (File (by its hash)), `url`, `domain`, `ip_address` (IP address).
- Item (`item`, text, required): The file's MD5, SHA-1 or SHA-256 hash, the URL, the domain or the IP address.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `comments` (list): The comments, newest first
- `count` (number): How many came back on this page
- `has_more` (true/false): True when there are more on later pages
- `item` (text): The item: a file hash, URL, domain or IP address
- `item_type` (text): What the item is: file, url, domain or ip_address
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page

**Example output**

```json
{
  "comments": [
    {
      "comment_id": "d-example.com-7d3b2e14",
      "posted_at": "2026-09-12T10:21:03+00:00",
      "tags": [
        "benign"
      ],
      "text": "Reserved for documentation by IANA. #benign",
      "votes_abuse": 0,
      "votes_negative": 0,
      "votes_positive": 4
    }
  ],
  "count": 1,
  "has_more": false,
  "item": "example.com",
  "item_type": "domain",
  "next_cursor": ""
}
```

### List communicating files

Get the files that contacted a domain or IP address when VirusTotal's sandboxes ran them, with each file's verdict: the quickest way to tell a malware server from an ordinary one.

**Inputs**

- Domain or IP address (`domain_or_ip`, text, required): A domain, like example.com, or an IPv4 or IPv6 address.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `count` (number): How many came back on this page
- `files` (list): The files
- `has_more` (true/false): True when there are more on later pages
- `item` (text): The domain or IP address
- `item_type` (text): domain or ip_address
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page

**Example output**

```json
{
  "count": 1,
  "files": [
    {
      "link": "https://www.virustotal.com/gui/file/e7a2b1f0c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c",
      "malicious": 54,
      "name": "invoice.exe",
      "sha256": "e7a2b1f0c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c",
      "suspicious": 1,
      "threat_label": "trojan.emotet/zusy",
      "type": "Win32 EXE",
      "verdict": "malicious"
    }
  ],
  "has_more": false,
  "item": "203.0.113.7",
  "item_type": "ip_address",
  "next_cursor": ""
}
```

### List subdomains

Get the subdomains VirusTotal has seen under a domain, with each one's verdict.

**Inputs**

- Domain (`domain`, text, required): The domain, like example.com.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `count` (number): How many came back on this page
- `domain` (text): The domain
- `has_more` (true/false): True when there are more on later pages
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page
- `subdomains` (list): The subdomains

**Example output**

```json
{
  "count": 1,
  "domain": "example.com",
  "has_more": false,
  "next_cursor": "",
  "subdomains": [
    {
      "domain": "www.example.com",
      "last_analyzed_at": "2026-09-27T16:40:12+00:00",
      "link": "https://www.virustotal.com/gui/domain/www.example.com",
      "malicious": 0,
      "suspicious": 0,
      "verdict": "clean"
    }
  ]
}
```

### List votes

Get how VirusTotal's community voted on a file, URL, domain or IP address: harmless or malicious, newest first.

**Inputs**

- What it is (`item_type`, text, required): Whether the item is a file (given by its hash), a URL, a domain or an IP address. One of: `file` (File (by its hash)), `url`, `domain`, `ip_address` (IP address).
- Item (`item`, text, required): The file's MD5, SHA-1 or SHA-256 hash, the URL, the domain or the IP address.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `count` (number): How many came back on this page
- `has_more` (true/false): True when there are more on later pages
- `item` (text): The item: a file hash, URL, domain or IP address
- `item_type` (text): What the item is: file, url, domain or ip_address
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page
- `votes` (list): The votes, newest first

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "item": "example.com",
  "item_type": "domain",
  "next_cursor": "",
  "votes": [
    {
      "verdict": "harmless",
      "voted_at": "2026-09-12T10:21:03+00:00"
    }
  ]
}
```

### Rescan

Have every engine look again, with today's signatures, at a file, URL, domain or IP address VirusTotal already knows, and wait for the fresh verdict.

**Inputs**

- What it is (`item_type`, text, required): Whether the item is a file (given by its hash), a URL, a domain or an IP address. One of: `file` (File (by its hash)), `url`, `domain`, `ip_address` (IP address).
- Item (`item`, text, required): The file's MD5, SHA-1 or SHA-256 hash, the URL, the domain or the IP address.
- Seconds to wait for the verdict (`wait_seconds`, number): How long to wait for every engine to answer, up to 300. A scan usually takes 20 to 60 seconds, and a large file longer. With 0 the scan only starts, and Get analysis reads its verdict later. From 0 to 300. Default: `60`.

**Outputs**

- `analysis_id` (text): The scan's ID, for Get analysis
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `finished` (true/false): True once every engine has answered. Until then the verdict is unknown and Get analysis reads it later
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `harmless` (number): How many security vendors say it is harmless
- `item` (text): The item: a file hash, URL, domain or IP address
- `item_type` (text): What the item is: file, url, domain or ip_address
- `link` (text): The item's page on VirusTotal
- `malicious` (number): How many security vendors flag it as malicious
- `status` (text): queued, in-progress or completed
- `suspicious` (number): How many security vendors flag it as suspicious
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet

**Example output**

```json
{
  "analysis_id": "NDRkODg2MTJmZWE4YThmMzZkZTgyZTEyNzhhYmIwMmY6MTc5MTE5NjM2NA==",
  "engine_count": 67,
  "finished": true,
  "flagged_by": [
    {
      "category": "malicious",
      "engine": "BitDefender",
      "result": "EICAR-Test-File (not a virus)"
    },
    {
      "category": "malicious",
      "engine": "Kaspersky",
      "result": "EICAR-Test-File"
    }
  ],
  "harmless": 0,
  "item": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "item_type": "file",
  "link": "https://www.virustotal.com/gui/file/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "malicious": 62,
  "status": "completed",
  "suspicious": 0,
  "undetected": 5,
  "verdict": "malicious"
}
```

### Scan file

Upload a file for some seventy antivirus engines to scan, and wait for the verdict. Files up to 650 MB. VirusTotal shares uploaded files with its security community, so don't scan anything confidential.

**Inputs**

- File (`file`, text, required): The file to scan: upload one, pick a file from an earlier step, or paste a link to one.
- ZIP password (`zip_password`, text): For a password-protected ZIP file, its password, so VirusTotal can open it and scan what is inside.
- Seconds to wait for the verdict (`wait_seconds`, number): How long to wait for every engine to answer, up to 300. A scan usually takes 20 to 60 seconds, and a large file longer. With 0 the scan only starts, and Get analysis reads its verdict later. From 0 to 300. Default: `60`.

**Outputs**

- `analysis_id` (text): The scan's ID, for Get analysis
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `file_name` (text): The name the file was uploaded under
- `finished` (true/false): True once every engine has answered. Until then the verdict is unknown and Get analysis reads it later
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `harmless` (number): How many security vendors say it is harmless
- `link` (text): The file's page on VirusTotal
- `malicious` (number): How many security vendors flag it as malicious
- `sha256` (text): The file's SHA-256 hash, for Get file report
- `size` (number): Its size in bytes
- `status` (text): queued, in-progress or completed
- `suspicious` (number): How many security vendors flag it as suspicious
- `undetected` (number): How many security vendors checked it and found nothing
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet

**Example output**

```json
{
  "analysis_id": "NDRkODg2MTJmZWE4YThmMzZkZTgyZTEyNzhhYmIwMmY6MTc5MTE5NjM2NA==",
  "engine_count": 67,
  "file_name": "eicar.com",
  "finished": true,
  "flagged_by": [
    {
      "category": "malicious",
      "engine": "BitDefender",
      "result": "EICAR-Test-File (not a virus)"
    },
    {
      "category": "malicious",
      "engine": "Kaspersky",
      "result": "EICAR-Test-File"
    }
  ],
  "harmless": 0,
  "link": "https://www.virustotal.com/gui/file/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "malicious": 62,
  "sha256": "275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f",
  "size": 68,
  "status": "completed",
  "suspicious": 0,
  "undetected": 5,
  "verdict": "malicious"
}
```

### Scan URL

Send a URL for some seventy security vendors to check for phishing and malware, and wait for the verdict. VirusTotal visits the URL and shares what it finds, so don't scan links with private tokens in them.

**Inputs**

- URL (`url`, text, required): The URL to scan, like https://example.com/page.
- Seconds to wait for the verdict (`wait_seconds`, number): How long to wait for every engine to answer, up to 300. A scan usually takes 20 to 60 seconds, and a large file longer. With 0 the scan only starts, and Get analysis reads its verdict later. From 0 to 300. Default: `60`.

**Outputs**

- `analysis_id` (text): The scan's ID, for Get analysis
- `engine_count` (number): How many security vendors gave a verdict: the 70 in '5 of 70'
- `finished` (true/false): True once every engine has answered. Until then the verdict is unknown and Get analysis reads it later
- `flagged_by` (list): The security vendors that flagged it, malicious first
- `harmless` (number): How many security vendors say it is harmless
- `link` (text): The URL's page on VirusTotal
- `malicious` (number): How many security vendors flag it as malicious
- `status` (text): queued, in-progress or completed
- `suspicious` (number): How many security vendors flag it as suspicious
- `undetected` (number): How many security vendors checked it and found nothing
- `url` (text): The URL scanned
- `url_id` (text): VirusTotal's ID for the URL, for Get URL report
- `verdict` (text): malicious when at least one security vendor flags it as malicious; suspicious when none does but one flags it as suspicious; clean when vendors checked it and none flagged it; unknown when there is no verdict yet

**Example output**

```json
{
  "analysis_id": "u-0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7-1791196364",
  "engine_count": 92,
  "finished": true,
  "flagged_by": [],
  "harmless": 68,
  "link": "https://www.virustotal.com/gui/url/0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7",
  "malicious": 0,
  "status": "completed",
  "suspicious": 0,
  "undetected": 24,
  "url": "https://example.com/",
  "url_id": "0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7",
  "verdict": "clean"
}
```

### Search

Look up a file hash, URL, domain or IP address in one step, each with its verdict, or find comments by tag. VirusTotal's free API searches by file hash only; the rest needs a premium key.

**Inputs**

- Search for (`query`, text, required): A file hash. With a premium key, also a URL, domain, IP address, or a tag such as phishing to find comments tagged with it.
- Maximum results (`limit`, number): How many to get, up to 40. From 1 to 40. Default: `10`.
- Next page (`cursor`, text): To get the next page, the next_cursor an earlier step returned. Leave it empty for the first page.

**Outputs**

- `count` (number): How many came back on this page
- `has_more` (true/false): True when there are more on later pages
- `next_cursor` (text): Give this as Next page to get the page after. Empty on the last page
- `query` (text): What was searched for
- `results` (list): What was found

**Example output**

```json
{
  "count": 1,
  "has_more": false,
  "next_cursor": "",
  "query": "example.com",
  "results": [
    {
      "id": "example.com",
      "item_type": "domain",
      "link": "https://www.virustotal.com/gui/domain/example.com",
      "malicious": 0,
      "suspicious": 0,
      "title": "example.com",
      "verdict": "clean"
    }
  ]
}
```
