node-argon2: password hashing bindings with a stated end state
Node.js bindings for Argon2 hashing algorithm
At a glance
- What is it?
- Native Argon2 bindings for Node that ship prebuilt binaries for Linux, macOS, Windows, Alpine and FreeBSD. The README is unusually candid: once Node's own crypto module covers Argon2, this package plans to become a thin wrapper over it.
- Who is it for?
- Use node-argon2 if you need PHC string parsing, a rehash check, or sane default parameters, because the README's comparison table lists all three as things `node:crypto` does not provide. Skip it if all you need is a raw Argon2 hash, since Node's own crypto module does that already and will keep doing it after this package thins down.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 34 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two functions and a deliberate default you should not touch
The usage section is short because the API surface is. Hashing looks like this:
const argon2 = require("argon2");
try {
const hash = await argon2.hash("password");
} catch (err) {
//...
}And verification takes the stored hash plus the plaintext, returning a boolean and throwing only on an internal failure:
try {
if (await argon2.verify("<big long hash>", "password")) {
// password match
} else {
// password did not match
}
} catch (err) {
// internal failure
}The distinction between a false return and a thrown error is the part to notice. A wrong password is a normal result, not an exception, so your error branch is for a malformed hash or a broken environment.
Three algorithm variants are available, with Argon2id as the default: Argon2i, Argon2d and Argon2id. The README also carries a callout worth repeating in your own codebase review: by default `argon2.hash` generates hashes according to the security recommendations of the team that develops Argon2, and for password hashing there is no need to modify them. Time cost, memory cost and parallelism, plus output length and encoding, live in a wiki page linked as Options.
TypeScript users get typings with the package and need no `@types` install. The declaration entry point is `argon2.d.cts` and the module is CommonJS, so the import style in the README is `import * as argon2 from "argon2"`.
The comparison table is the most important thing on the page
The README contains a table comparing node-argon2 against `node:crypto`'s native Argon2, and it is worth reading as a statement of intent rather than as marketing. It says the native API is focused on generic use of the Argon2 hash function, while this package historically focused on password hashing.
Against that, four rows come out in this package's favour: PHC string formatting, verifying a PHC string, checking if a rehash is needed, and providing sensible default parameters. Each is marked absent in the `node:crypto` column. Those are real gaps. PHC string parsing in particular is the difference between storing a hash you can identify as Argon2 with its parameters attached and storing an opaque blob, and a rehash check is how you migrate parameters when they change without forcing every user to reset their password.
Then the paragraph that follows is the one to weigh before you adopt this. The README states that once all supported Node releases include native Argon2 and older versions are officially end-of-life, node-argon2 will transition into a minimal wrapper: it will offer the developer-friendly interface, bridge users to Node's native crypto methods, avoid duplication, and guarantee upgrades once native support is universal.
That is a project telling you its own feature list will shrink. It is an honest thing to publish and it does change the decision. If you adopt it for PHC handling and the rehash check, those are the parts that survive. If you adopt it for Argon2 itself, you are depending on a layer that plans to step aside.
The README also links a wiki article on migrating from another hash function, which is the practical starting point if you are moving off bcrypt or a native scrypt call.
Prebuilt binaries cover six platforms, and the fallback is a C++ toolchain
Prebuilt binaries have shipped since v0.26.0 and are rebuilt on every release through GitHub Actions. The listed build and test matrix is specific enough to check against your own target:
- Ubuntu 22.04 (x86-64; ARM64 from v0.28.2; ARMv7 from v0.43.0) - MacOS 13 (x86-64) - MacOS 14 (ARM64 from v0.29.0) - Windows Server 2022 (x86-64) - Alpine Linux 3.18 (x86-64 from v0.28.1; ARM64 from v0.28.2; ARMv7 from v0.43.0) - FreeBSD 14 (x86-64 from v0.29.1; ARM64 from v0.44.0)
The README also explains the compatibility rule: binaries should work on anything more recent, so the Ubuntu 20.04 binary works on 22.04 or any Linux with a newer glibc, and the macOS 11 binary works on macOS 12. Going backwards is what fails.
If no prebuilt binary fits, the README's Before installing section is the cost you pay. You must have node-gyp installed globally, GCC 5 or newer or Clang 3.3 or newer, and on Windows you must compile under Visual Studio 2015 or newer. The package is stated to work only and be tested against Node 22 or newer, which lines up with the v0.45.0 release dropping Node 18 and 20 support with the parenthetical that it probably still works but is not tested.
On macOS the documented path is `brew install gcc`, then `npm install -g node-gyp`, then `CXX=g++-12 npm install argon2`. That last detail is easy to miss: if your compiler binary is named something other than `g++-12`, you have to say so in `CXX` or the build fails in a way that is hard to read.
Two escape hatches when a prebuilt binary will not do
The FAQ section covers the cases where the automatic path breaks. The first is a manual rebuild of the binary in place, and it names a specific tool choice:
npx @mapbox/node-pre-gyp rebuild -C ./node_modules/argon2The README explains why the `@mapbox` fork rather than plain node-pre-gyp: node-argon2's `binding.gyp` relies on variables from `@mapbox/node-pre-gyp`. You can drop the `npx @mapbox` prefix if you have a global install, otherwise npx picks up the local copy in `node_modules/.bin`.
The second case is forcing a source build at install time, in either of two forms. Force it during install:
npm install argon2 --build-from-sourceOr bypass the install script and build yourself afterwards:
npm install argon2 --ignore-scripts
npx node-gyp rebuild -C ./node_modules/argon2The two-step form is what you want in CI where you need to see the compiler output rather than a swallowed install failure.
The third FAQ entry is the one that catches people most often: if you installed Node as a snap and cannot install this package, the README attributes it to a snap issue, links a comment on issue 345, and suggests installing Node with asdf or nvm instead. Snap's confinement is the cause, and no amount of build flags will get around it.
A thin binding layer over a vendored copy of the reference code
The tree is small and tells you the whole architecture: `argon2.cpp` as the N-API entry point, `binding.gyp` for the build, `argon2.cjs` as the runtime entry point, `test.cjs` for the tests, plus a submodule directory named `argon2/` holding the C sources, the blake2 implementation, the Argon2 LICENSE and its own CHANGELOG.
The `package.json` confirms the details. The package name is `argon2` while the repository is node-argon2, so `require("argon2")` is what your code imports. The binary section declares a single N-API version, `8`, which is what makes one prebuilt binary work across Node versions rather than needing a separate build per release. `main` is `argon2.cjs` and `types` is `argon2.d.cts`, so the published package is CommonJS with bundled declarations.
The runtime dependencies are four: `@phc/format`, which is where the PHC string parsing comes from, `node-addon-api` for the N-API layer, `node-gyp-build` for picking a prebuilt binary at install time, and `cross-env`, present so the install script can set `ZERO_AR_DATE=1` cross-platform. That last variable is the one to know about: it forces the zero-overhead random number generator to always reseed, which costs performance and is there to stop a subtle class of weak-randomness bug.
The build tooling has moved to the oxc family. Formatting and linting are `oxfmt` and `oxlint`, the build script itself is `prebuildify --napi --strip --tag-armv --tag-libc`, tests run on Node's built-in test runner with `node --test test.cjs`, and type declarations are compiled with `tsc` on prepare. There are no compiled output directories in the tree and no bundled runtime dependency tree, which keeps the install footprint small.
MIT is the declared license, and the vendored Argon2 sources carry their own LICENSE inside the submodule, which is the correct arrangement and worth preserving if you vendor this yourself.
Editorial conclusion
Use node-argon2 if you need PHC string parsing, a rehash check, or sane default parameters, because the README's comparison table lists all three as things `node:crypto` does not provide. Skip it if all you need is a raw Argon2 hash, since Node's own crypto module does that already and will keep doing it after this package thins down. Verify one thing before committing: that your platform has a prebuilt binary for your architecture, because the fallback is compiling from source and needs node-gyp, GCC 5 or Clang 3.3 or newer, and Visual Studio 2015 or newer on Windows. The last push was on 2026-09-07 and v0.45.1 shipped on 2026-07-21, so the project is current, but the README's own plan is for its feature set to shrink rather than grow.
Frequently asked questions
Which is better, bcrypt or Argon2?
This package hashes with Argon2, choosing from Argon2i, Argon2d and Argon2id with Argon2id as the default, and the README states the defaults follow the security recommendations of the Argon2 team. It links a wiki article on migrating from another hash function for moving an existing bcrypt-derived store across.
Is Argon2 better than SHA256?
For password storage they are not comparable in the way that phrasing suggests. A general-purpose hash such as SHA256 is fast, which is the property you want for integrity checks and exactly the wrong property for passwords, since speed lets an attacker try candidates quickly. node-argon2 exists so you are not hashing passwords with a fast function in the first place.
What are the prebuilt binaries for node-argon2 and what if mine is missing?
Prebuilt binaries ship from v0.26.0 onwards for Ubuntu, MacOS, Windows Server 2022, Alpine and FreeBSD across x86-64, ARM64 and, from v0.43.0, ARMv7 on Linux. If your platform is older than the matrix, you compile from source, which needs node-gyp, GCC 5 or newer or Clang 3.3 or newer, and Visual Studio 2015 or newer on Windows.
Why should I not change the Argon2 hash parameters?
The README states that `argon2.hash` generates secure hashes according to the security recommendations by the team that develops Argon2, and that for password hashing there is no need to modify them. Time cost, memory cost, parallelism, hash length and encoding are all configurable and documented on the project's wiki.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ranisalt-node-argon2)