/install virustotal3
VirusTotal Skill — Public API
Interact with the VirusTotal Public API v3 to scan files, URLs, domains, and IP addresses for malware analysis and threat intelligence.
Configuration
API Key
Secrets file: Store your API key in a file (default: ~/.openclaw/secrets/virustotal.env):
VIRUSTOTAL_API_KEY=your_api_key_here
Create with chmod 600. Get your API key from https://www.virustotal.com/gui/my-apikey.
Loading: All curl examples use . (dot) source to load credentials into the shell environment:
. "${VIRUSTOTAL_SECRETS_FILE:-$HOME/.openclaw/secrets/virustotal.env}"
Override the default path with the VIRUSTOTAL_SECRETS_FILE environment variable.
⚠️ Credential Security (MANDATORY)
NEVER display secrets in tool output. The . source command loads credentials into shell variables silently — no output is produced. This is the correct and secure approach.
Banned patterns:
cat ~/.openclaw/secrets/virustotal.envVIRUSTOTAL_API_KEY=xxx curl ...- Any form of reading secrets into tool output
If credential loading fails: Fix the secrets file path or contents. Do NOT bypass security by hardcoding values.
Request Pattern
All endpoints use this secure pattern. Replace {PATH} with the endpoint path and add any extra flags as needed:
. "${VIRUSTOTAL_SECRETS_FILE:-$HOME/.openclaw/secrets/virustotal.env}" \
&& _H=$(mktemp) && chmod 600 "$_H" \
&& printf 'x-apikey: %s\
' "$VIRUSTOTAL_API_KEY" > "$_H" \
&& curl -s "https://www.virustotal.com/api/v3{PATH}" -H@"$_H" \
&& rm -f "$_H"
For POST requests add -X POST and appropriate data flags after the URL.
For file uploads replace the curl URL with the upload URL and add -F "file=@/path/to/file".
Response Structure
All endpoints return JSON with this common shape:
{
"data": {
"id": "resource_identifier",
"type": "file|url|domain|ip_address|analysis",
"attributes": {
"reputation": 0,
"last_analysis_stats": {
"malicious": 0,
"suspicious": 0,
"harmless": 0,
"undetected": 0
},
"last_analysis_results": {
"EngineName": {
"category": "harmless|malicious|suspicious|undetected",
"result": "clean|Trojan.Generic|phishing|unrated",
"engine_update": "20230101",
"engine_version": "1.0.0"
}
}
}
}
}
Per-endpoint unique fields:
- File:
sha256,md5,sha1,names,size,type_description - URL:
url,title - Domain:
whois,creation_date,last_update_date,last_dns_records,last_https_certificate,rdap - IP:
country,as_owner,network,tags - Analysis:
status("completed"|"queued"|"in-progress"|"failed"),stats
API Overview
- Base URL:
https://www.virustotal.com/api/v3 - Authentication:
x-apikeyheader (loaded from secrets file, see Request Pattern) - Rate limit: 4 requests/minute (free tier). Premium has no limits.
- Response format: JSON (see Response Structure)
File Operations
File Scan (Upload)
Endpoint: POST /files
Description: Upload and scan a file with VirusTotal. Returns an analysis ID.
File size limits:
- Direct upload: up to 32MB
- Large files (up to 650MB): Use
/files/upload_urlendpoint first
curl example:
# Replace {PATH} in the request pattern above with: /files
curl -s -X POST "https://www.virustotal.com/api/v3/files" -H@"$_H" -F "file=@/path/to/file"
See Response Structure above. Unique fields for this endpoint: id, type.
Error handling:
- 400: Invalid file, password-protected ZIP, or corrupt file
- 429: Rate limited
- 401: Invalid API key
File Report (by Hash)
Endpoint: GET /files/{id}
Description: Get analysis report for a file by its hash (MD5, SHA1, or SHA256).
curl example:
# Replace {PATH} in the request pattern above with: /files/{hash}
curl -s "https://www.virustotal.com/api/v3/files/{hash}" -H@"$_H"
See Response Structure above. Unique fields for this endpoint: sha256, md5, sha1, names, size, type_description.
Large File Upload (32MB+)
Endpoint: POST /files/upload_url
Description: Get a URL for uploading files larger than 32MB (up to 650MB).
curl example:
# Replace {PATH} in the request pattern above with: /files/upload_url
curl -s "https://www.virustotal.com/api/v3/files/upload_url" -H@"$_H"
URL Operations
URL Scan (Submit)
Endpoint: POST /urls
Description: Submit a URL for scanning. Returns an analysis ID.
curl example:
# Replace {PATH} in the request pattern above with: /urls
curl -s -X POST "https://www.virustotal.com/api/v3/urls" -H@"$_H" --form-urlencode "url=https://example.com"
See Response Structure above. Unique fields for this endpoint: id, type.
URL Report
Endpoint: GET /urls/{id}
Description: Get analysis report for a URL. The {id} parameter should be a URL identifier (not the raw URL - see URL identifiers below).
URL identifiers: Convert URLs to identifiers using base64 encoding of - prefixed URL:
echo -n "https://example.com" | base64 # returns aHR0cHM6Ly9leGFtcGxlLmNvbQ==
curl example:
# Replace {PATH} in the request pattern above with: /urls/{url_id}
curl -s "https://www.virustotal.com/api/v3/urls/{url_id}" -H@"$_H"
See Response Structure above. Unique fields for this endpoint: url, title.
Domain & IP Operations
Domain Report
Endpoint: GET /domains/{domain}
Description: Get analysis report for a domain.
curl example:
# Replace {PATH} in the request pattern above with: /domains/{domain}
curl -s "https://www.virustotal.com/api/v3/domains/example.com" -H@"$_H"
See Response Structure above. Unique fields for this endpoint: whois, creation_date, last_update_date, last_dns_records, last_https_certificate, rdap.
IP Address Report
Endpoint: GET /ip_addresses/{ip}
Description: Get analysis report for an IP address.
curl example:
# Replace {PATH} in the request pattern above with: /ip_addresses/{ip}
curl -s "https://www.virustotal.com/api/v3/ip_addresses/8.8.8.8" -H@"$_H"
See Response Structure above. Unique fields for this endpoint: country, as_owner, network, tags.
Analysis Status
Endpoint: GET /analyses/{id}
Description: Check the status of an analysis (file or URL scan).
curl example:
# Replace {PATH} in the request pattern above with: /analyses/{analysis_id}
curl -s "https://www.virustotal.com/api/v3/analyses/{analysis_id}" -H@"$_H"
See Response Structure above. Unique fields for this endpoint: status ("completed"|"queued"|"in-progress"|"failed"), stats.
Error Handling
Common HTTP Status Codes
| Code | Description | Action |
|---|---|---|
| 200 | Success | Process response |
| 400 | Bad Request | Check request parameters |
| 401 | Unauthorized | Verify API key |
| 403 | Forbidden | Check permissions, premium required |
| 404 | Not Found | Resource doesn't exist |
| 429 | Too Many Requests | Rate limited - wait and retry |
| 500 | Internal Server Error | Server error - try again later |
Rate Limiting (429)
When you receive a 429 response:
- Wait at least 60 seconds before retrying
- Free tier: maximum 4 requests per minute
- Consider implementing exponential backoff
- Premium tier: no rate limits
Error Response Format
{
"error": {
"code": "error_code",
"message": "Error description"
}
}
Free vs Premium Features
Free Tier (This Skill)
- ✅ File scanning (32MB direct, 650MB with upload URL)
- ✅ URL scanning
- ✅ Domain reports
- ✅ IP address reports
- ✅ Basic threat intelligence
- ❌ Search/Retrohunt (premium only)
- ❌ Livehunt/YARA rules (premium only)
- ❌ Advanced threat hunting (premium only)
- ❌ Private API access (premium only)
- ❌ Bulk operations (premium only)
- ❌ Priority processing (premium only)
Premium Features
- No rate limits
- Advanced threat hunting
- Search/Retrohunt functionality
- Livehunt notifications
- Private API access
- Bulk operations
- Priority processing
- Extended retention
URL Identifier Generation
For URL reports, you need to encode the URL as follows:
# Method 1: Using base64
URL="https://example.com"
URL_ID=$(echo -n "$URL" | base64)
echo "$URL_ID" # aHR0cHM6Ly9leGFtcGxlLmNvbQ==
# Method 2: Using Python
python3 -c "import base64; print(base64.b64encode(b'https://example.com').decode())"
Best Practices
- Rate limiting: Implement proper rate limiting (4 requests/minute for free tier)
- Error handling: Always check HTTP status codes and handle errors gracefully
- Security: Never expose API keys in logs or tool output
- Caching: Cache responses when possible to reduce API calls
- File uploads: Use upload_url for files larger than 32MB
- Analysis polling: For file/URL scans, poll the analysis endpoint for completion
Last updated: 2026-05-24
- Make sure OpenClaw is installed (local or Docker)
- Run the install command in chat:
/install virustotal3 - After installation, invoke the skill by name or use
/virustotal3 - Provide required inputs per the skill's parameter spec and get structured output
What is virustotal?
Free malware, network and IP analysis! Scan files, URLs, domains, and IPs with VirusTotal. Use when the user asks to scan, check, or analyze a file, URL, dom... It is an AI Agent Skill for Claude Code / OpenClaw, with 20 downloads so far.
How do I install virustotal?
Run "/install virustotal3" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.
Is virustotal free?
Yes, virustotal is completely free, licensed under MIT-0. You can download, install and use it at no cost.
Which platforms does virustotal support?
virustotal is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).
Who created virustotal?
It is built and maintained by arfonzo (@arf0nz0); the current version is v1.0.0.