Bcrypt is an adaptive password-hashing function designed by Niels Provos and David Mazières in 1999, built around a deliberately expensive variant of the Blowfish key-setup schedule. It was created specifically to make password cracking expensive, in contrast with general-purpose hashes like SHA-256 that are tuned for raw speed.
This tool runs the pure-JavaScript bcryptjs library in your browser. The same library is used on the server side by countless Node.js applications, so a hash you generate here is bit-for-bit interchangeable with one produced by Express, NestJS, or any backend that calls bcrypt.hash. No password ever leaves your tab - bcryptjs runs synchronously on the main thread (or via a small worker for the async API) and never makes a network request.
Every bcrypt output is a single self-describing string of the form $2a$10$<22-char-salt><31-char-hash>. The version prefix ($2a$, $2b$, $2y$) declares the algorithm variant, the next field is the log-2 cost factor, and the rest is a custom Base64 encoding (called bcrypt64) of a 16-byte salt followed by a 24-byte derived key. Because everything needed to verify a password is embedded in the string, you only have to store one column in your database.
The cost factor is the only knob that matters for security. Each increment doubles the work: cost 10 means 2^10 = 1024 internal iterations of the EksBlowfish key schedule, cost 12 means 4096, cost 14 means 16384. On a 2024-class laptop, cost 10 takes around 50-80 ms, cost 12 around 200-300 ms, cost 14 well over a second. OWASP's 2024 password storage guidance recommends cost 10 as a floor and increasing it as your hardware gets faster.
Bcrypt has one well-known limitation: passwords are silently truncated at 72 bytes. Anything beyond byte 72 of the UTF-8 encoded password is ignored entirely. For most users this is fine, but if you accept arbitrary-length passphrases you should pre-hash with SHA-256 (or switch to Argon2id, which has no such cap). The verify step here will report a match against the truncated portion, exactly as a real server would.
Salt handling is automatic: bcryptjs calls a CSPRNG (window.crypto.getRandomValues in the browser) to produce 16 fresh random bytes for every call. That means hashing the same password twice yields two completely different output strings, which is exactly what you want - it defeats rainbow tables and prevents identical passwords from being visible as identical hashes in a database leak.
The verifier on this page is a thin wrapper around bcrypt.compare, which re-derives the hash using the salt and cost factor embedded in the candidate string and performs a constant-time comparison of the result. That last detail matters: a naive == comparison would leak timing information about which byte differed, opening up timing attacks against poorly written login endpoints.