"bcrypt decode", "bcrypt hash to text", "bcrypt decrypt online" — these searches get thousands of hits a month, and every result promising to do it is either confused or a scam. Let's clear this up properly. bcrypt is a hash, not encryption Encryption is a two-way street: encrypt with a key, decrypt with a key. A hash is a one-way function by design. bcrypt takes a password and produces a fixed digest; there is no key, and no inverse function exists. This isn't a limitation to work around — it's the entire point. If a database leaks, the attacker gets digests, not passwords. So when someone asks "how do I decrypt this bcrypt hash?", the real question is almost always one of these three: Case 1: "I need to check if a password matches" You never decode the hash — you hash the candidate password with the same salt and compare. Every bcrypt library does this for you: // Node.js const bcrypt = require("bcryptjs"); const ok = await bcrypt.compare("hunter2", storedHash); // true / false # Python import bcrypt ok = bcrypt.checkpw(b"hunter2", stored_hash) The salt is embedded in the hash string itself (that's what the $2b$10$... prefix carries), so compare needs nothing else. Case 2: "A user forgot their password" You can't recover it, and that's correct behavior. The only legitimate flow is a reset: send a time-limited, single-use token to a verified channel, let the user set a new password, hash the new one. Any site that can email you your old password is storing it wrong — treat that as a red flag as a user, and never build it as a developer. Case 3: "I'm testing / doing a CTF and need to crack it" What people call "decrypting" here is really guessing: hash candidate passwords until one matches. Tools like hashcat automate this against wordlists. This is exactly the attack bcrypt is built to resist — its work factor (cost) makes each guess slow, so strong passwords remain out of reach even offline. It works only against weak passwords, and only do this on systems you're authorized to test. Reading a bcrypt string $2b$10$N9qo8uLOickgx2ZMRZoMye.IjPeVUxkJDrz8vd3AJlDpMH0W3iBGe │ │ └──────────┬─────────┘└──────────────┬───────────────┘ │ │ salt (22 chars) digest (31 chars) │ └─ cost factor: 2¹⁰ = 1,024 rounds └─ algorithm version The cost factor is the tunable part. 10 is a common default; raise it as hardware gets faster. Each +1 doubles the work. Try it yourself If you want to see how the same password produces different hashes (random salt) and how compare still works, I built a small bcrypt hash generator that runs entirely in the browser — generate, tweak the cost factor, and verify, with nothing sent to a server. TL;DR bcrypt cannot be decrypted. Nothing can "convert a bcrypt hash to text." To verify: bcrypt.compare(candidate, hash). Forgot password → reset flow, never recovery. "Cracking" = brute-force guessing, which bcrypt deliberately makes slow.