pompelmi vs Alternatives

There are several ways to integrate ClamAV into a Node.js application. This page compares pompelmi against the most commonly used alternatives, based on objective criteria such as API design, maintenance status, TypeScript support, streaming capability, and privacy characteristics.

All of the Node.js libraries listed below are open source. The goal of this comparison is to help you choose the right tool for your project — not to dismiss any of them.

Feature Comparison

Feature pompelmi clamscan clamav-js node-clam VirusTotal API
Maintained Yes No — last release 2017 Infrequently Yes Yes (SaaS)
TypeScript declarations Full — bundled .d.ts None None Community @types Depends on SDK used
Buffer / in-memory scan Yes — scanBuffer(buf) No — file path only No — file path only Via temp file Yes
Readable stream scan Yes — scanStream(stream) No No No No
S3 / cloud storage scan Yes — scanS3() No No No Yes (upload to API)
Runtime verdicts Verdict.Clean / Malicious / ScanError
(Symbol-based — typo-proof)
String / exit code String / exit code Callback / boolean JSON object
clamd TCP / socket mode Yes — both No — clamscan CLI only TCP only Yes — both N/A
Zero npm dependencies Yes (core) 1–2 deps Multiple native bindings Several deps HTTP client + SDK deps
No data egress / privacy Data never leaves your server Local — data stays on server Local — data stays on server Local — data stays on server Files sent to VirusTotal servers
Framework plugins Express, Next.js, NestJS, Fastify, Hono None None None REST API
CLI tool Yes — pompelmi scan No No No Web UI / REST
Connection pool Yes — createPool() No No No Rate limited
Directory watcher Yes — watch(dir) No No No No
Cost Free (ISC) / Enterprise $49.99/mo Free (MIT) Free Free (MIT) Paid API quota
Bun support Yes No No Untested Yes

About each alternative

clamscan (npm)

A thin wrapper around the clamscan CLI binary. It spawns a child process for every scan, making it slower than the INSTREAM protocol. The last npm release was in 2017 and the package is effectively unmaintained. No TypeScript declarations, no stream support, and no buffer scanning.

Best for: legacy scripts where clamd is not available and a one-off file scan is sufficient.

clamav-js

Uses native bindings via node-gyp to call the libclamav C API. Native bindings add build-time complexity, break on Node.js version upgrades, and are hard to use in Docker or serverless environments. No TypeScript declarations, no stream or buffer scanning API.

Best for: offline scanning without a running daemon, where native binding complexity is acceptable.

node-clam

A more feature-complete ClamAV wrapper that supports both the CLI and clamd TCP modes. It has more dependencies than pompelmi and a more complex configuration API. Community-maintained TypeScript types are available via DefinitelyTyped. Buffer and stream scanning are not directly supported; files must be on disk.

Best for: teams already using node-clam who want incremental improvements without migrating.

vs SaaS (VirusTotal, Cloudmersive, etc.)

SaaS antivirus APIs offer multi-engine scanning (VirusTotal checks 70+ engines) and require no on-premise infrastructure. However:

pompelmi keeps scanning fully in-process. Files never leave your infrastructure, there is no per-scan cost, and latency is bounded by local network (typically under 10 ms for clamd over UNIX socket).

Which should you choose?

Choose pompelmi if…

You need TypeScript support, stream / buffer scanning, framework plugins, Bun compatibility, or a clean Symbol-based API. Privacy and zero egress matter.

Choose node-clam if…

You already depend on node-clam and don't want to migrate, or need legacy Node.js support (< 18).

Choose VirusTotal if…

You need multi-engine coverage, do not process sensitive data, and the per-scan cost and latency are acceptable for your use case.

Choose clamav-js if…

You need offline scanning without any running daemon and native bindings are acceptable in your build environment.

Questions? Open a GitHub issue or contact us.