Both are real password hashing algorithms — deliberately slow, salted, built to resist exactly the kind of offline cracking that makes a raw SHA-256 or MD5 hash worthless for password storage. Neither is "broken" the way MD5 is. The honest answer to "which should I use" is more nuanced than "always pick the newer one," and the differences that actually matter are more specific than most comparisons let on.
At a glance
| bcrypt | Argon2 | |
|---|---|---|
| Introduced | 1999, by Niels Provos and David Mazières | 2015, winner of the Password Hashing Competition |
| Built on | EksBlowfish (expensive key setup over the Blowfish cipher) | A custom memory-hard construction, purpose-built for this job |
| Tunable parameters | One — cost factor (time only) | Three — memory, iterations, parallelism |
| Memory hardness | Fixed ~4 KB, not configurable | Configurable, typically tens of MB |
| Max input length | 72 bytes — silently truncated beyond that | 2³²−1 bytes (~4.29 GB) — a non-issue in practice |
| OWASP status | Acceptable, cost factor ≥ 10 | Recommended default (Argon2id specifically) |
Where each came from
bcrypt is the older of the two by 16 years. Niels Provos and David Mazières introduced it in 1999, building it around EksBlowfish — an "expensive key setup" variant of the Blowfish cipher that repeats its key-scheduling step 2cost times before it's ever used to encrypt anything. That repeated key setup, not the encryption itself, is the actual password hash — it's slow by construction, and the cost factor controls exactly how slow.
Argon2 exists because of a deliberate, public effort to do better. The Password Hashing Competition ran from 2013 to 2015 — the same open, adversarial-review process used for AES and SHA-3 — and evaluated 24 submitted designs. On July 20, 2015, it selected Argon2, designed by Alex Biryukov, Daniel Dinu, and Dmitry Khovratovich at the University of Luxembourg, as the winner, with special recognition for four runners-up: Catena, Lyra2, yescrypt, and Makwa. Unlike bcrypt, which repurposes a cipher built for something else, Argon2 was designed from scratch for exactly one job.
The core difference: memory-hardness
This is the distinction that actually matters most. bcrypt's EksBlowfish key setup keeps its S-boxes — about 4 KB of constantly accessed, constantly modified data — in memory during every round. That was a genuinely clever defense in 1999: it meant an attacker couldn't trivially pipeline the computation, and it made bcrypt meaningfully harder to accelerate than a plain hash function. But it's fixed. There's no parameter that lets you ask bcrypt to use more memory.
Argon2's memory cost is a parameter you set — typically tens of megabytes, not a few kilobytes. That difference compounds against exactly the hardware an attacker would actually use. GPUs and custom ASICs are extremely good at running billions of parallel guesses; what they're not good at is giving every one of those parallel cores its own large chunk of fast memory. 4 KB per attempt is nothing to provision at scale. Tens of megabytes per attempt is expensive to provision at scale — that's the entire point of a memory-hard function, and it's the gap bcrypt's design couldn't close because it predates the concept.
The 72-byte ceiling
bcrypt has a hard limit that surprises people who haven't hit it: it only processes the first 72 bytes of whatever you give it, silently. A 100-character passphrase and the same passphrase with 30 extra random characters appended produce the identical bcrypt hash, because bcrypt never sees the difference. It's rarely a practical problem — 72 bytes is a very long password — but it's a real, documented limitation, not a myth. Argon2's spec (RFC 9106) caps the password input at 2³²−1 bytes — about 4.29 GB — which is not a limit any real password will ever approach.
Three knobs vs one
bcrypt has exactly one tunable: the cost factor, which controls time and nothing else. That simplicity is arguably a feature — there's only one way to misconfigure it (too low), and it's easy to reason about. Argon2id has three independent parameters — memory, iterations, and parallelism — which is more powerful but also more surface area for a misconfiguration to quietly weaken the hash. Parallelism in particular is easy to get wrong: raising it speeds up hashing on multi-core hardware, but it doesn't add security margin by itself the way raising memory or iterations does, which is exactly why OWASP's baseline profile keeps parallelism at 1 and does the real work through memory and iteration count instead.
A quick timing comparison
Hashing the same password with bcrypt at OWASP's minimum cost factor (10) and Argon2id at OWASP's minimum profile (19,456 KiB memory, 2 iterations, 1 lane), using the same WebAssembly library on the same machine:
bcrypt (cost=10) -> ~57-85ms
argon2id (m=19456, t=2, p=1) -> ~48-59msClose enough that raw speed isn't the deciding factor between them — this is one WASM implementation on one machine, not a rigorous cross-platform benchmark, and a native library will land on different numbers. The memory-hardness gap above is the difference that actually holds up under a real attack, not the millisecond count on your own laptop.
Practical guidance
- Starting a new project? Use Argon2id. It's the current OWASP default recommendation, its memory-hardness is a genuine advantage against GPU/ASIC cracking, and mature libraries exist in every major language now.
- Already running bcrypt in production? That's not an emergency. bcrypt with a properly maintained cost factor (10+, raised as your server can tolerate) is still considered acceptable — migrating an existing user base off it is a real engineering effort with its own risks, and "newer algorithm exists" alone doesn't justify a rushed migration. Rehash-on-login as users authenticate is the standard, low-risk path if you do move.
- Working in an older or more constrained ecosystem? bcrypt's simplicity and near-universal library support (it's been implemented correctly for 25 years) can be a real advantage over a newer, three-parameter algorithm where a well-meaning but wrong configuration is easy to ship.
- Never use a raw hash function like SHA-256 or MD5 for either — see Password Hashing Explained for why.
Try it yourself
Password Hash Generator builds real bcrypt and Argon2id/i/d hashes (plus scrypt and PBKDF2) with configurable parameters, Password Hash Inspector decodes an existing hash you already have back into its cost factor or memory/iteration settings, and Bcrypt Cost Calculator benchmarks real bcrypt timing at increasing cost factors to help you pick one for a target latency. All three run entirely in your browser.