Skip to content

Bcrypt Playground

Educational tool. Production passwords must be hashed server-side, never in the browser. This playground exists to help you understand how bcrypt works and to inspect existing hashes (e.g. from a leak scan or database export).

Estimates for educational purposes — not financial, medical, or legal advice. See terms.

Bcrypt is the most widely-used password hashing function in production — most web frameworks default to it, most security guides recommend it, and most stored-password breaches you read about involve hashes that bcrypt produced. This playground gives you a browser-side place to experiment with bcrypt’s behaviour: generate hashes at different cost factors, verify candidate passwords against existing hashes, see what the output format looks like.

It is not a production password hashing tool. The notes throughout this page repeat that because client-side password hashing is one of those security mistakes that looks reasonable until you think it through; the box at the top of the form makes the same point.

How bcrypt works

Bcrypt is based on the Blowfish cipher, designed in 1999 by Niels Provos and David Mazières specifically for password hashing. The key properties:

  • One-way. Given a hash, you can verify a candidate password but you cannot derive the original.
  • Salted. Every hash includes a random 16-byte salt, so the same password produces a different hash each time. Defeats rainbow-table attacks.
  • Tunable cost. A cost factor (4-14 in this tool, up to 31 in the spec) controls how many iterations bcrypt runs. Each step roughly doubles the time, letting you tune the cost as hardware gets faster.

The hash format is $2a$<cost>$<salt><digest> — exactly 60 characters. The salt and digest portions use a base64 variant; the algorithm prefix and cost are plain text.

The cost factor explained

Cost 10 takes ~100ms on a 2020-era laptop. Each step doubles:

CostTime on 2020 laptopUse
4~5msTest code, tutorials
8~25msLow-traffic sites with weak threat model
10~100msEducational baseline (default here)
12~400ms2026 production minimum
14~1.6sHigh-value accounts

Production systems pick the highest cost the user-facing latency budget tolerates. ~250-500ms during login is the practical sweet spot for most web apps; longer makes the login feel sluggish, shorter doesn’t slow attackers enough.

Example: generating a hash

Type “correct horse battery staple” into the password field. Set cost to 10. Click Generate hash. Output: something like $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy. Copy. Run again — different hash (different salt). Both verify correctly against the original password.

Example: verifying a hash from a database

You’re investigating a database export. A user record contains the bcrypt hash above. Switch to Verify mode. Paste “correct horse battery staple” and the hash. Click Verify. Result: ✓ Match, cost 10, took ~100ms. Try “wrong password” — ✗ No match.

Example: estimating attack time

A determined attacker with one mid-range GPU rig can compute roughly 100,000 bcrypt-cost-10 hashes per second. For an 8-character random alphanumeric password (62^8 = ~218 trillion combinations), the expected time to brute-force is ~35,000 years at that rate. Increasing cost to 12 makes it 4× slower; doubling password length raises the search space by ~218 trillion. This is why bcrypt + a long random password defeats brute-force at any practical scale, but bcrypt + “password123” doesn’t (a few seconds against a dictionary attack).

Common mistakes

Hashing client-side and sending the hash. Defeats the purpose. The hash becomes the password; an attacker sniffing it gets full access. Always send the plain password over TLS to the server, hash there.

Re-hashing an existing bcrypt hash. If your DB column contains hashes and you accidentally hash them again on migration, the result is a hash of a hash — which doesn’t verify against the original password. Migrations that change the hashing strategy need to mark records for re-hash on next login, not bulk re-hash.

Picking cost factor by guessing. Benchmark on your production hardware. The tool’s estimate is a 2020-era reference; a 2026 server CPU is meaningfully faster, mobile is slower. Measure under realistic load before committing to a cost.

Storing the cost separately. The cost is encoded in the hash. Don’t store it as a separate column; you’ll desync it.

What this tool does not do

It doesn’t transmit anything to a server. The bcryptjs library runs entirely in your browser; passwords and hashes never leave your device. (This is also why you can’t use it for production hashing — see the warning at the top.)

It doesn’t compare hash speeds against other algorithms (argon2, scrypt). For modern systems, argon2id is generally preferred over bcrypt where available; bcrypt remains popular because of inertia and ecosystem support.

It doesn’t crack hashes. There’s no built-in dictionary or brute-force mode. For real password cracking (audit, recovery), use hashcat or john-the-ripper with a proper wordlist on hardware suited to the task. For general-purpose non-password hashing (file fingerprints, message digests), the hash generator produces SHA-256/384/512; bcrypt is deliberately slow and the wrong tool for those.

Frequently asked questions

Should I use this tool to hash production passwords?

No. Production password hashing must happen server-side, never in the browser. Doing it client-side defeats the purpose: the cost factor's compute is paid by the user's device (so an attacker on a fast machine has the advantage); the salt becomes attacker-visible in network traffic; and the plain password reaches the browser before it ever hashes, so any compromised script can intercept it. Real systems hash on a trusted server with a server-side library (Node bcryptjs, Python bcrypt, Go x/crypto/bcrypt, etc.). This playground is for understanding bcrypt's behaviour, not for running production auth.

What does the cost factor do?

Cost factor is bcrypt's work parameter. Each step roughly doubles the time to compute the hash. Cost 10 (the default) takes ~100ms on a 2020-era laptop; cost 14 takes ~1.6 seconds; cost 4 (the minimum) is near-instant. Higher cost makes brute-force attacks slower at the same hardware level. As GPUs and ASICs get faster over the years, the recommended minimum cost increases — production systems in 2026 typically use cost 12-14. Cost is encoded in the hash, so future verification at the same cost still works.

Why are two hashes of the same password different?

Bcrypt generates a random 16-byte salt for every hash and embeds it in the output. So `hashPassword('foo')` called twice produces two different hashes — both verifying correctly against 'foo' but with different salt+digest portions. This is by design: same password, different salts means an attacker who finds two users with the same password can't tell from the stored hashes alone. Salting also prevents rainbow-table attacks against precomputed hash lists.

What does '$2a$10$...' mean in the hash?

The bcrypt hash format is `$<algorithm>$<cost>$<salt+digest>`. `$2a$` is the algorithm version (2a, 2b, 2y are all bcrypt variants — 2b is the modern standard, 2a is older but still supported, 2y is a PHP-specific variant). `10` is the cost factor. The remaining 53 base64-ish characters are the 22-character salt followed by the 31-character digest. Total hash length is always 60 characters.

Why doesn't the verify mode tell me the original password?

Bcrypt is a one-way hash by design. There's no way to derive the original password from the hash — you can only verify whether a candidate password matches by re-hashing it with the same salt and comparing. If you've forgotten a password and only have its hash, your options are: try common candidates (dictionary attack), brute-force (slow, exponentially worse with longer passwords), or accept that the original is gone. The verify mode here lets you test specific candidate passwords against an existing hash — useful for inspecting a hash from a leak scan or recovering access to your own systems.