Bcrypt Hash Generator & Verifier

Generate a bcrypt password hash or verify a password against an existing hash, entirely in your browser. Passwords never leave your device.

🌐 Español

🔒 Private by design: your text is processed locally in your browser and never uploaded to any server.

Two generically labelled boxes, and which one takes the password

This page borrows the site’s two-box comparison layout, so the textareas carry that component’s generic names instead of password-specific ones. The mapping is fixed, and it is worth learning before you paste anything sensitive.

  1. Paste the password into the first box, labelled Original text.
  2. Leave Mode on Generate a new hash, or switch it to Verify a password against an existing hash.
  3. In generate mode, set the cost factor field, which accepts 4 to 12 and starts at 10, and ignore the second box. If you leave text in it anyway, the report says at the end that it was ignored.
  4. In verify mode, paste the bcrypt hash you are checking against into the second box, labelled Changed text.
  5. Click Bcrypt Hash Generator & Verifier. The result appears in a read-only panel with Copy to clipboard underneath it.

The button stays disabled until at least one of the two boxes has something in it.

Every hash carries its own salt

Generate a hash for the same password twice and you get two different strings. That is bcrypt working, not failing. A fresh random salt is generated on every call and stored inside the output, which is why a bcrypt hash is 60 characters rather than a bare digest: a $2 variant marker, a two-digit cost factor, then 53 characters holding the 22-character salt and the 31-character digest together.

Two consequences follow, and both catch people out in real code. You can never check a password by comparing hash strings, because the stored hash was made with a salt your fresh hash will not reuse; you have to hand the password and the stored hash to bcrypt’s own compare function, which is precisely what verify mode does here. And a stolen table of bcrypt hashes resists precomputed rainbow tables, because every row was salted differently and has to be attacked on its own.

Cost 10 by default, and why the field stops at 12

The cost factor is an exponent. The work performed is 2 to the power of the cost, so each step of +1 roughly doubles the time a single hash takes. Slowness is the feature: an attacker who steals the database pays the same price per guess that you paid per login, which is the whole distinction between a password hash and a checksum.

The field accepts 4 to 12 and starts at 10, a common real-world default. The ceiling is there because this is a pure-JavaScript bcrypt running inside your tab rather than native code on a server. Timings measured against this exact library while the tool was built put cost 12 near a fifth of a second and cost 18 near thirteen seconds for one hash; your machine will land somewhere else, but the doubling behaves the same, and a capped field beats an accidental multi-minute freeze. Values that are fractional or outside the range are rounded and clamped into the 4 to 12 window before hashing. The asynchronous library API is used rather than the blocking one, and no request leaves the page at any point.

Reading the report the tool prints

The output is a labelled plain-text block, not a bare hash, and it repeats your input back at you. Generate mode echoes the password in quotes with a character count, states the cost factor and the number of rounds it expands to, prints the hash on its own line, and appends a note about the changing salt. Verify mode echoes the password and the hash under test, prints the cost factor it read back out of that hash, and finishes with one of MATCH, NO MATCH or INVALID HASH FORMAT.

That third status exists for a specific reason. The underlying compare function does not object to most malformed hashes; it simply answers “no”, which is indistinguishable from a wrong password. So the shape is checked first, after trimming surrounding whitespace, and a string that fails that check is reported as a format problem instead of a mismatch. In one respect that shape check is looser than the library it guards: it accepts a $2x version marker, which the library itself rejects as an invalid revision, so such a hash reaches neither status and surfaces as the shell’s generic error notice instead. Note also that the character count is over code points rather than bytes, which only matters if you are near bcrypt’s own 72-byte input limit with multi-byte characters.

Bcrypt against the fast hashes on this site

SHA-256 and the MD5 generator here exist to fingerprint pasted text. They are fast by design, and that speed is exactly what disqualifies them for password storage, because speed is the attacker’s budget too. Bcrypt is deliberately slow, salted per row, and tunable upward as hardware improves.

For the jobs either side of this one: the password generator produces the random string you would then hash, the password strength checker estimates how long a given password would survive a guessing attack before you commit to it, and the htpasswd generator wraps this same bcrypt library into a complete username:hash line for an Apache or Nginx basic-auth file, reusing this page’s own cost bounds and default.

See it in action

Screenshot of the Bcrypt Hash Generator & Verifier tool with the sample input “a-strong-demo-password”, Mode set to Generate a new hash, Cost factor (2^cost rounds), generate mode only set to 10
Bcrypt Hash Generator & Verifier mid-process: the sample input “a-strong-demo-password”, Mode set to Generate a new hash, Cost factor (2^cost rounds), generate mode only set to 10.
Screenshot of the Bcrypt Hash Generator & Verifier result screen showing the generated output “=== BCRYPT HASH GENERATOR & VERIFIER === Mode: G…”
The finished result: the generated output “=== BCRYPT HASH GENERATOR & VERIFIER === Mode: G…”. The download link is a local blob URL — the file never leaves your device.

Frequently asked questions

Why is the second box labelled "Changed text" when I am pasting a hash into it?

Because the page reuses the site's two-box text comparison layout rather than shipping a second, nearly identical form, and the labels come from that shared component. The mapping never varies, so the first box is always the password and the second box is always the existing hash. Only verify mode uses the second box; in generate mode anything left in it is ignored, and the report says so at the end rather than silently swallowing it.

Can I verify a hash that was generated somewhere else, in PHP or Python?

Yes, provided it is a real bcrypt hash in the standard 60-character form with a $2a, $2b or $2y marker. Verification needs only the password and the stored string, because the salt and the cost factor travel inside the hash itself. A hash produced by a different algorithm, or one that lost characters in a copy and paste, is reported as an invalid format rather than as a wrong password. One marker is worth knowing about because it behaves differently from both of those outcomes. $2x, an old PHP crypt() revision, gets past the shape check this page runs, but the bcrypt library underneath refuses that revision outright, so a $2x hash produces the shared shell's generic error notice instead of a verdict or an invalid-format report. Verify those where they were created.

Verify mode shows a different cost factor from the one I set. Is that a bug?

No. Verify mode reads the cost factor out of the hash you pasted and prints what it found there, because the cost is stored in the hash as two digits immediately after the version marker. That is exactly what lets a system keep verifying old hashes after raising the cost for new ones. The number field applies to generate mode only.

Can I hash a whole list of passwords, one per line?

No. The entire first box is treated as a single password, newlines included, so five passwords on five lines produce one hash of that whole block. Hash them one at a time, clicking Compare another between runs to clear both boxes.

What happens if I click the button with one of the boxes empty?

You still get a readable report rather than a failure. Generate mode with an empty password prints a NO PASSWORD PROVIDED status and names the box to use. Verify mode does the same for a missing password, and prints NO HASH PROVIDED when the password is there but the second box is not filled in. Every outcome is written as report text on purpose, since the shared shell would otherwise swallow it and show one generic error.

Is a bcrypt hash safe to commit to a repository or paste into a config file?

It is far safer than the password, which is the entire reason hashes are stored, but it is not harmless. A weak password behind a low cost factor can still be attacked offline by anyone who obtains the hash. Use a cost you can afford, keep hashes out of public repositories where you have the choice, and remember that the report on this page also quotes your password in clear text, so copy the hash line rather than the whole block.

Related tools