The password never leaves the browser. Hashing a password on a generic online service is a security contradiction: you are sending a clear-text credential to a third party. Here the computation happens entirely inside the tab, in JavaScript and WebAssembly, with no network request at all. You can verify it by opening the Network panel of your developer tools: type a password, generate the hash, and no HTTP request goes out. Once loaded, the page even works offline.
Passwords must not be hashed with fast functions. MD5, SHA-1 and SHA-256 are designed to be blazing fast: a modern GPU computes billions of them per second. Applied to a stolen database, that speed works for the attacker, who can try huge dictionaries of passwords in no time. On top of that, without a salt, identical passwords produce identical hashes and become vulnerable to precomputed rainbow tables. bcrypt and Argon2 do the opposite: they are deliberately slow and tunable, so every attempt costs the attacker time (and, for Argon2, memory too).
The salt is already inside the hash. A bcrypt hash like $2y$12$R9h/cIPz0gi.URNNX3kh2O... is a self-contained package: $2y$ is the version, 12 is the cost factor, the next 22 characters are the salt (128 random bits) and the rest is the actual digest (184 bits). For Argon2id, the output $argon2id$v=19$m=19456,t=2,p=1$salt$hash embeds version, memory/time/parallelism parameters, salt and digest. You do not need to store the salt in a separate column: verifying means reading those parameters back from the hash and recomputing. That is why password_verify() only needs the password and the hash, nothing else.
bcrypt or Argon2id: which one. For a new project the 2026 recommendation is Argon2id, which is memory-hard: it forces the attacker to spend a lot of RAM per attempt, neutralising the advantage of GPUs and ASICs that chew through bcrypt instead. bcrypt is still perfectly valid, it is everywhere (PHP, Laravel, Spring, Node) and has no special dependencies: its historical limit is that it truncates the password at 72 bytes and is not memory-hard. If your stack supports Argon2id, prefer it; if you must stay compatible with a bcrypt ecosystem, an adequate cost factor is still a solid choice.