Skip to content

vt-scanner: Check Any File Against VirusTotal in One Command

If you handle suspicious files — malware samples, email attachments, downloads from sketchy URLs — you've done the dance: hash the file, open VirusTotal, paste the hash, wait, repeat. It's slow, manual, and burns your attention on process instead of analysis.

I built vt-scanner, a CLI that automates the entire workflow. Point it at a directory and it hashes every file, checks VirusTotal, caches results, and tells you what's clean and what's not. No browser tabs, no copy-paste, no wasted API calls.

vt-scanner

What it does

Three subcommands, each for a different workflow:

scan — one-shot audit

vt-scanner scan ./malware-samples

Hashes every file, checks VT, prints a verdict table:

FILE                                 VERDICT    ENGINES  NAME                LAST SEEN
──────────────────────────────────── ────────── ──────── ─────────────────── ────
samples/legit-setup.exe              CLEAN       0/72   setup_installer      2026-10-15
samples/backdoor.dll                 MALICIOUS  12/72   Trojan.Generic       2026-10-18
samples/unknown.bin                  UNKNOWN       -    -                         -

Malicious files are highlighted in red, suspicious in yellow, clean in green. JSON output is available for scripting.

monitor — continuous watch

vt-scanner monitor ~/Downloads --interval 60

Monitors a directory forever. New or modified files get hashed and checked automatically. Good for a malware analysis VM, a shared download folder, or monitoring where you drop samples during triage.

cache — don't waste API calls

vt-scanner cache stats

Every lookup is stored in a local SQLite database. If a file hasn't changed (same path, same modification time), the cached result is reused — zero API hits. This is the main upgrade over the manual copy-paste workflow.


Install and run

pip install git+https://github.com/barry-oc/vt-scanner.git
export VT_API_KEY="your_key_here"

vt-scanner scan ./samples
vt-scanner monitor ./incoming --interval 30

VirusTotal free tier allows 4 requests per minute. The scanner spaces requests automatically — set --rate-limit if you have a higher-tier key.


Why I built this

The original version of this tool was a loop-and-sleep Python script I'd been using for months. It worked but had all the usual raw-script problems:

  • API key hardcoded in the file
  • time.sleep(30) between every request regardless of rate limit
  • Results printed as unformatted Python objects
  • No caching — same file checked 50 times
  • Only SHA-256

The rewrite adds proper CLI design (argparse, three subcommands), structured caching (SQLite with path+mtime tracking), formatted output (color tables + JSON), and support for SHA-256, SHA-1, and MD5. Same core idea, but it doesn't feel like a script someone duct-taped together at 2am.


Pipe it

JSON output makes it scriptable:

# Find all malicious files
vt-scanner scan ./samples --json | jq '.[] | select(.result.last_analysis_stats.malicious > 0)'

# Export clean files to a list
vt-scanner scan ./samples --json | jq -r '.[] | select(.result.last_analysis_stats.malicious == 0) | .path' > clean.txt

Run it on your samples. github.com/barry-oc/vt-scanner

Pull requests and feature ideas welcome — especially if you have an edge case in your malware workflow I haven't thought of yet.