bcrypt is the Blowfish cipher with a deliberately ruinous key schedule. Blowfish normally sets itself up once per key; bcrypt, as Provos and Mazières designed it in 1999, starts from Blowfish’s tables — the hexadecimal digits of pi — mixes in the salt and the password, then repeats that expensive setup 2^cost times, alternating password and salt, before encrypting the text “OrpheanBeholderScryDoubt” 64 times. The hash records all of it: $2b$, a two-digit cost, 22 characters of salt and 31 of result, in bcrypt’s own base64 alphabet (./A–Za–z0–9, not the usual one). The cost is an exponent, so each step up doubles the time: cost 10 is 1,024 rounds and cost 12 is 4,096. OWASP’s Password Storage Cheat Sheet asks for at least 10, the default here.
The limit people trip over is 72 bytes. The key schedule reads eighteen 32-bit words of password and never more, so everything after byte 72 is ignored — not rejected, ignored. It counts bytes of UTF-8, not characters: 72 ASCII letters fill it, but so do 36 Greek letters or 18 four-byte emoji. A longer password matches any other password with the same first 72 bytes, and when byte 72 falls inside a character only part of that character counts. This tool says when either happens. Go’s x/crypto/bcrypt and pyca/bcrypt 5.0 refuse to hash such passwords instead. A NUL character is refused here outright, because libraries disagree about it: the C implementations stop reading at the first one, while Go and Python hash straight through it.
The letter after $2 records bugs, not a different algorithm. In 2011 crypt_blowfish, the implementation in PHP and several Linux distributions, was found to mishandle bytes above 127 (CVE-2011-2483); the fixed version writes $2y$, and $2x$ marks hashes made with the bug on purpose so they can still be checked. In 2014 OpenBSD fixed a bug of its own — the password length was kept in 8 bits, so passwords of 255 bytes or more wrapped round — and introduced $2b$. For any text password all three prefixes give the same hash here; what differs is who accepts the label. PHP and Apache write $2y$, OpenBSD and pyca/bcrypt write $2b$, Go writes $2a$, and OpenBSD refuses $2y$. Both halves run in a Web Worker, so a high cost cannot freeze the page, and checking recomputes the hash and compares it in constant time.