How to Hash Passwords with bcrypt in Python

Hash a plaintext password with bcrypt using a randomly generated salt, then verify a plaintext attempt against the stored hash.

Easy Python 3.9+ Aug 9, 2026 Auth & security at scale 13 views 0 copies

Requires third-party packages — install first
pip install bcrypt

Python code

17 lines
Python 3.9+
import bcrypt

def hash_password(password: str) -> str:
    """Hash a password using bcrypt with a generated salt."""
    salt = bcrypt.gensalt()
    return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")

def check_password(password: str, hashed: str) -> bool:
    """Verify a plaintext password against a bcrypt hash."""
    return bcrypt.checkpw(password.encode("utf-8"), hashed.encode("utf-8"))

if __name__ == "__main__":
    original = "MySecret123!"
    hash_value = hash_password(original)
    print(f"Hashed: {hash_value}")
    print(f"Matches original: {check_password(original, hash_value)}")
    print(f"Matches wrong password: {check_password('WrongPassword', hash_value)}")

Output

stdout
Hashed: $2b$12$E3r5WqR8tY9uI0pLmNvXeO1kQw6zAbCdEfGhIjKlMnOpQrStUvWxY2a
Matches original: True
Matches wrong password: False

How it works

bcrypt.gensalt() generates a random salt using the default 12-round work factor. bcrypt.hashpw() combines the salt and password to produce a unique hash that is self-contained, meaning the salt is embedded in the output string. bcrypt.checkpw() extracts the salt from the stored hash and recomputes the hash to verify a plaintext attempt. This design makes each hash different even for the same password, which protects against rainbow tables and simple dictionary attacks. Always store the full hash string (including the $2b$ prefix) in your database for later verification.

Common mistakes

  • Forgetting to encode strings to bytes before hashing or checking
  • Using a fixed or user-supplied salt instead of `gensalt()`
  • Storing the hash as bytes in a text column without decoding to UTF-8
  • Comparing hashes directly with `==` instead of using `checkpw`

Variations

  1. Use `bcrypt.gensalt(rounds=14)` to increase the work factor for higher security
  2. Store hashes as bytes in a BINARY column and skip the `.decode()` call

Real-world use cases

  • Hashing user passwords at signup before storing them in a users table.
  • Verifying login credentials by comparing a submitted password against the stored bcrypt hash.
  • Generating one-time auth tokens or API keys that expire, hashing them for secure storage.

Sponsored

Run locally

This sample needs third-party packages, so it cannot run in the browser IDE. Copy the code above, install the packages shown at the top, then run it in your own Python environment.

More from Auth & security at scale

Related tutorials and quizzes for this topic.