A typed Python SDK and JSON-first command-line client for authorized VirusShare research workflows. Search through an authenticated account, retrieve API v2 metadata, download bounded password-protected archives, and inspect ZIP metadata without extracting sample content.
Caution
VirusShare distributes malware samples. Use this package only with an authorized account and inside an isolated analysis environment. The library never extracts or executes archive members, but downloaded files remain dangerous.
This project is not affiliated with VirusShare.
- Capabilities
- Quick start
- Search
- Reports and status
- Bounded downloads
- Inspect without extracting
- Data flow
- Development
- Security
| Operation | Access path | Credentials | Safety behavior |
|---|---|---|---|
| Search | Authenticated website | Username and password | Explicit page bound through --pages |
| File report | API v2, then website fallback | API key or account credentials | Structured JSON response |
| Quick status | API v2 | API key | Read-only request |
| Source information | API v2 | API key | Read-only request |
| Archive download | API v2 or authenticated website | API key or account credentials | Explicit risk acknowledgement, size cap, ZIP validation, atomic finalization |
| Local archive inspection | Local filesystem | None | Reads central-directory metadata only |
The web search and API v2 paths are separate because they expose different VirusShare functionality. Search parsing depends on authenticated HTML, so a site markup change can affect search while API operations continue to work.
Python 3.11 or newer is required.
git clone https://github.com/ntkrnlmp/virusshare.git
cd virusshare
python -m venv .venv
.venv\Scripts\python -m pip install -e ".[dev]"Set credentials in the process environment. The package does not load .env files automatically.
$env:VIRUSSHARE_USERNAME = "your_username"
$env:VIRUSSHARE_PASSWORD = "your_password"
$env:VIRUSSHARE_API_KEY = "your_optional_api_key"Account credentials are required for website search. The API key is optional unless an API v2 operation is requested.
The CLI emits JSON that can be redirected or piped into another tool.
virusshare search 'extension:pdf detgte:5 limit:10'
virusshare search 'filetype:"PE32\+ .*" limit:20' --pages 2One page is fetched by default. --pages sets an explicit upper bound.
Synthetic output shape, using the repository test fixture rather than a live sample:
{
"displayed_from": 1,
"displayed_to": 1,
"elapsed_seconds": 0.001,
"next_skip": null,
"query": "filetype:synthetic limit:1",
"results": [
{
"download_url": null,
"fields": {
"file_type": "synthetic test fixture",
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"report_url": null,
"sha256": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
],
"skip": 0
}The Python client includes a structured query builder:
from virusshare import VirusShareClient
with VirusShareClient.from_env() as client:
page = client.search_fields(
{
"filetype": r"PE32\+ .*",
"detgte": 10,
"after": "-7 days ago",
"limit": 10,
}
)
for result in page.results:
print(result.sha256, result.fields.get("file_type"))search_fields() rejects unknown contexts. Use search() when working with raw or newly introduced VirusShare syntax.
virusshare report <hash>
virusshare quick <hash>
virusshare source <sha256>quick and source require an API key. report prefers API v2 and falls back to the authenticated website when only account credentials are available.
Downloads require an explicit acknowledgement:
virusshare download <hash> --output .\downloads --accept-risk
virusshare download <hash> --output .\downloads\sample.zip `
--max-bytes 67108864 --accept-riskThe download path:
- Streams into a temporary file with a 256 MiB default maximum.
- Stops if the configured byte limit is exceeded.
- Calculates the archive SHA-256 digest while writing.
- Checks that the result is a non-empty, valid ZIP container.
- Moves the completed archive into place atomically.
Existing files are preserved unless --overwrite is supplied. The returned digest covers the ZIP archive, not its member. VirusShare archives are normally password protected with infected, and this package leaves them encrypted.
from virusshare import VirusShareClient
with VirusShareClient.from_env() as client:
receipt = client.download(
"<hash>",
"downloads",
max_bytes=64 * 1024 * 1024,
)
print(receipt.path, receipt.size, receipt.archive_sha256)virusshare inspect .\downloads\sample.zipThe command hashes the archive and reads ZIP central-directory metadata. It does not open or extract member content. Absolute paths, drive prefixes, and .. components are marked with suspicious_path: true.
Important
A clean metadata inspection does not make extraction safe. Keep the archive encrypted and move deeper analysis into a purpose-built malware lab.
flowchart LR
A[CLI or Python API] --> B[VirusShareClient]
B --> C[Authenticated web search]
B --> D[API v2 metadata]
B --> E[Bounded archive stream]
E --> F[Temporary file]
F --> G{Size and ZIP checks pass?}
G -->|Yes| H[Hash and atomic move]
G -->|No| I[Delete temporary file and raise error]
H --> J[Encrypted ZIP remains unextracted]
Requests are restricted to https://virusshare.com. Short service failures and rate-limit responses are retried, but the client does not attempt to bypass quotas or access controls.
python -m pytest -q
python -m ruff check .CI runs both checks on Python 3.11, 3.12, and 3.13. Tests use a mock transport and synthetic fixtures, so they require neither live samples nor account credentials.
Keep samples, collected reports, credentials, and reverse-engineering projects out of pull requests.
Before using the client:
- Review the current VirusShare account rules, API documentation, and request limits.
- Confirm that the planned automation is permitted by the account terms and local law.
- Store credentials outside the repository and rotate any exposed secret.
- Download only into an isolated system with no personal or production data.
- Do not extract or execute samples on a workstation.
Do not open a public issue containing credentials, malware, or account details. Use GitHub private vulnerability reporting and provide a minimal reproduction built from synthetic data.