zxcvbn-python

A Python port of Dropbox's zxcvbn - realistic password strength estimation with crack-time estimates and specific improvement feedback.

Library
PyPI
v4.5.0
716stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
40/100Fair
Development Activity8
Maintenance0
Community64
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
70/100Good
Architecture78
Code Quality66
Innovation80
Learning Curve55

zxcvbn-python is a faithful Python port of Dropbox’s zxcvbn, the pattern-based password strength estimator that scores passwords by simulating how a real attacker’s cracking dictionaries and pattern rules would guess them, rather than relying on naive length/character-class rules.

Passing a password (and optionally a list of user-supplied context like name or birthdate) to zxcvbn() runs it through dictionary, spatial, repeat, sequence, date, and l33t matchers, computes the minimum-guess sequence via dynamic programming, and returns a 0-4 score alongside crack-time estimates for four attack profiles and targeted feedback for improving the password.

What You Get

  • A single zxcvbn() call that returns a full strength report: numeric score (0-4), guess count, crack-time estimates across four attack scenarios, and human-readable feedback
  • Pattern matchers for dictionary words, keyboard adjacency (qwerty/dvorak/keypad), l33t-speak substitutions, dates, repeats, and sequences
  • Bundled frequency dictionaries (English Wikipedia, common passwords, first/last names, TV & film titles) used to rank how guessable a matched pattern is
  • A zxcvbn CLI entry point for scoring a password piped via stdin or entered interactively, in addition to the importable API

Common Use Cases

  • Real-time password strength meters on signup and change-password forms
  • Server-side validation to reject weak passwords before they’re hashed and stored
  • Security audits or scripts that batch-score existing or candidate password lists
  • Feeding user-supplied context (name, email, birthdate) into scoring so the check catches personally-guessable passwords generic rules miss

Under The Hood

Architecture zxcvbn-python is a small, flat package (zxcvbn/) organized as a linear pipeline rather than a class hierarchy: matching.py runs a battery of pattern detectors (dictionary, spatial/adjacency, repeat, sequence, date, l33t) over the input password via omnimatch, scoring.py’s most_guessable_match_sequence then applies a dynamic-programming search over the candidate matches to find the non-overlapping sequence that minimizes total guesses, time_estimates.py converts that guess count into crack-time estimates for four attack scenarios, and feedback.py derives human-readable suggestions from the winning match sequence; __init__.py’s top-level zxcvbn() function is the sole orchestration point wiring these stages together, and __main__.py wraps the same function for a stdin/interactive CLI. The large frequency-list dictionaries (English Wikipedia, passwords, names, surnames, TV/film titles) are lazy-loaded once behind a module-level cache (get_ranked_dictionaries) so importing the package doesn’t pay the cost of parsing megabytes of word lists until scoring actually runs; a change to the core omnimatch/most_guessable_match_sequence contract would ripple through every matcher and the CLI, since nothing else re-implements pattern detection independently.

Tech Stack The project has effectively zero runtime dependencies - it’s pure Python (3.8 through 3.13, per tox.ini and the GitHub Actions matrix) using only the standard library (re, functools, datetime, decimal, argparse, getpass, select) for its scoring engine. Packaging is classic setuptools (setup.py) with a console-script entry point (zxcvbn = zxcvbn.__main__:cli) rather than a pyproject.toml/build-backend setup, and dev/test tooling is pytest (version pinned by Python version in requirements.txt) run through tox across the full supported interpreter matrix, wired into GitHub Actions (.github/workflows/build.yml) alongside a mypy -p zxcvbn --ignore-missing-imports check.

Code Quality Test coverage is real and reasonably broad: eight files under tests/ exercise the matchers (matching_test.py, adjacency_graphs_test.py, l33t_exploit_test.py), the scoring engine (scoring_test.py), crack-time output (time_estimates_test.py), and the top-level zxcvbn() entry point (zxcvbn_test.py, covering unicode input, empty passwords, and non-string user_inputs), plus test_compatibility.py, which diffs output against a fixed password_expected_value.json to catch scoring-behavior regressions against the upstream JS implementation. Error handling is minimal but deliberate - zxcvbn() raises ValueError past max_length, and the suite explicitly checks that an empty password doesn’t raise IndexError. Type annotations are absent from the source itself (functions rely on default arguments and duck typing), though CI still runs mypy --ignore-missing-imports as a lightweight sanity check rather than full type enforcement; there’s no linter/formatter config (no ruff, black, or flake8 files) in the repo.

API Design The public surface is deliberately tiny - a single zxcvbn(password, user_inputs=None, max_length=72) call returns one dict carrying the score, guess count, crack-time estimates for four attack profiles, and structured feedback, so integrating a strength check into a signup form is a one-line call with no setup or configuration required. The user_inputs parameter is a notably ergonomic touch: passing a user’s name or email folds it straight into the ranked-dictionary matching so personally-guessable passwords are penalized without callers having to write their own blocklist logic. A small CLI (zxcvbn command, or python -m zxcvbn) mirrors the same function for ad-hoc or scripted use via stdin. The trade-off is that the API mirrors the original JS zxcvbn’s shape closely (a nested dict rather than a typed result object), which keeps it faithful to upstream but gives consumers loosely-typed dict access rather than autocomplete-friendly attributes.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search