Before you change jobs, ship a new site, or “just add an exclamation mark” to an old password, a lot of people search whether that string has already leaked. Results for “password strength checker,” “Have I Been Pwned,” and “online leak lookup” sit next to each other and sound like they answer the same question. Open the pages and the protocols split: some POST the input box to their own host, some ask a third party for a list of hash suffixes, and some download a public weak-password wordlist and compare it in the tab. Those three flows give three different answers to “did the password leave this page.”

This piece does not recap a Weak / Medium / Strong meter, and it does not teach you to attack anyone else’s database. The question is narrower: what a local leaked-password list can prove, and what a full-web lookup can prove, if it is implemented honestly. MyPassGen’s strength check is the first kind: the candidate is not uploaded; the page matches a public weak-password list that loads with the site; every tool opens without an account. The rest of this article lays the boundary out, then shows how to confirm it in DevTools Network.

Three different “password checks”

Name the protocols first. Marketing copy can say “local,” “never uploaded,” and “checked against breaches” in the same sentence while pointing at three different designs.

Method What leaves the browser Question it can answer
Hand the password to a website Plaintext, or a reversible form field The other host says it “checked” — you cannot see the evidence
k-anonymity range query (HIBP) The first 5 hex characters of a SHA-1 or NTLM hash Whether that hash appears in the corpus they maintain
Local match against a public weak-password list A static wordlist file, not your input Whether it is a repeatedly abused string such as 123456 or password

The first method is the easiest to use and the hardest to audit. A page can promise to “delete the query immediately.” Logs, backups, and analytics scripts can still keep a copy. The second is the design Have I Been Pwned documents for Pwned Passwords: the browser hashes first, sends only the prefix to api.pwnedpasswords.com/range/{prefix}, then matches suffixes locally. The third never sends even a prefix. The wordlist is a public set of common weak passwords — usually hundreds to ten thousand rows, not “every dump on the internet.”

The U.S. National Institute of Standards and Technology, in NIST SP 800-63B-4, tells verifiers to check a new or changed password against a list of “commonly used, expected, or compromised” values, and not to stack mandatory upper/lower/digit/symbol composition rules on top. It also says the blacklist’s main job is to block the guesses an online attacker tries first; once the list is larger than the rate-limit window, extra rows buy little. That is exactly where a local top list sits: a first sieve for common weak passwords, not a search of every breach file.

Pick the question before you pick the tool

“Would a dictionary try this first?” and “did this string appear in a specific dump?” are different sentences. A local list answers the first. A full-corpus range query answers the second only for the corpus the other party actually holds. Neither replaces the rule: do not reuse one password across sites.

What handing the plaintext to a site means

A number of “online password checkers” still put the input-box string into the request body. Some name the JSON field password. Some drop it into the query string. Some apply a reversible encoding and POST that. To the browser, the traffic looks like a login form: the far host, the reverse proxy, and the access log can all see this submission.

HTTPS only stops eavesdroppers on the path. It does not stop the far end writing plaintext to disk, and it does not stop an analytics script forwarding the field. What you are trying to reduce is whether this one check created another party who now knows the string. That is not HTTPS’s job. The previous article, how to verify that browser encryption did not upload plaintext, uses the same rule: slogans cannot prove it; traffic can.

There is a quieter way to hand it over: put the candidate in a query parameter, then forward the URL to a coworker or drop it into a ticket. Query strings land on the request line and in the far-end log. Some third-party resources still receive path and query in Referer. If the string is a live account password, that step is you spreading it. The safe default is: a real password stays in the current tab’s input box. Do not write it into a URL, and do not paste it into a “checker” that uploads the original.

A full-corpus lookup that only sends a prefix

Have I Been Pwned’s range API splits “search a large corpus” from “hand over the original.” The documented steps are: encode the password as UTF-8, compute SHA-1 (NTLM is also offered), take the first five hex characters, and request GET https://api.pwnedpasswords.com/range/{prefix}. The response is a list of suffixes and occurrence counts, separated by a colon. The client stitches prefix and suffix back together on the device and looks for a full match. Troy Hunt describes this as k-anonymity in Understanding Have I Been Pwned's Use of SHA-1 and k-Anonymity: the server sees a hash bucket, not the full hash, and not the password.

When Cloudflare published the design with HIBP, it gave numbers you can still check against the post: with a 5-character prefix, the median bucket held about 305 hashes, and the median response was about 12.2 KB. The API also offers Add-Padding: true, which pads each response to roughly 800–1,000 lines so an observer cannot infer “this was a very common password” from response length alone. All of that makes a range query far more restrained than POSTing plaintext — and it is still an outbound request. Network will show a call to api.pwnedpasswords.com. Disconnect the network and this kind of lookup should fail.

A range query is also not “perfect anonymity.” The prefix tells an observer which of 165 buckets your hash fell into. If page script copies the original before it sends the prefix, k-anonymity does not help. Email search and password search are also not the same API: HIBP v3 uses a 6-character prefix for hashed email range queries, and that is a different product surface. This article only compares “does this password appear in a password corpus.” It does not treat mailbox subscriptions or domain monitoring as the same check.

So “we use HIBP” is not the same sentence as “the password never left the device.” The accurate version is: the original and the full hash are not sent, by design; a prefix and one range request do leave. If you accept “a third party that maintains the corpus learns the hash bucket,” that is a reasonable engineering trade. If you require “this check must not send even a prefix,” use the local list in the next section, and accept a much smaller coverage.

A local list only fetches a wordlist

A local match runs the other way: download a public weak-password list to the current origin, then do a set lookup in script. Network may show the wordlist. It must not show the candidate from the input box. The list itself is public data. A typical source is a “top N of ten million passwords” file in SecLists, maintained around OWASP / Daniel Miessler’s collection. It answers “would an attacker’s first dictionary try this,” not “is this sitting in some unpublished dump.”

MyPassGen’s strength check follows that boundary. After the page opens it requests data/leaked-top10k.txt: about 860 lines, one lowercase password per line, starting with strings such as 123456, password, and qwerty. Matching happens in the browser: lowercase first, then a short set of variants — treat @ / 4 as a, 0 as o, and similar common leet, plus strip one to three trailing digits — then test the set. A hit is marked Weak even when the string looks “long.” If the wordlist fails to load, the script falls back to a tiny built-in set (password, 123456, and a few others). It does not switch to an external breach API.

The strength bar is a second local calculation. The character pool adds 26 + 26 + 10 + 32 depending on whether lower, upper, digits, and symbols appear. Entropy is roughly length times log2(pool), then discounted when too many characters repeat. The grade thresholds are: below about 40 bits Weak, below 60 Medium, below 80 Strong, and 80 and above Very strong. Length under 8 gets its own “too short” hint. The random generator allows 6–128 characters and defaults to 16. Offline brute-force is estimated at 1010 guesses per second; online rate-limiting at 103 — order-of-magnitude figures for you to read, not a promise about a particular GPU. Analytics events record the grade and whether the list hit. They do not send the password.

You can check those numbers on this machine: count wordlist lines in an editor or with wc -l. Network should show the wordlist and should not show the input. That still cannot be written as “we searched the whole web.” About 860 rows do not even cover SecLists’ public Top 10,000, let alone a hash-indexed corpus the size of HIBP’s. The only honest conclusion from a miss is: it is not a common weak password on this list.

A miss is not “safe” and not “never leaked”

A local list blocks the front of a dictionary. Your password can still sit in a dump outside the list, in a credential-stuffing combo, or in guesses aimed at your site. When you need a new password, generate one on this device. Do not keep the old word and append a year or an exclamation mark.

A strength bar does not prove a miss

A strength bar estimates search space. It does not search an archive. A 20-character random password can have high entropy and still already exist in someone else’s leak file. Attackers will not walk the charset from the start; they will try the ready-made list. The other way around, Password1! often satisfies a “must include upper, lower, digit, symbol” form and almost always sits on a public weak-password list. That reuse pattern is why NIST dropped composition rules.

If a check page shows both a strength grade and a list result, the list should override the bar: a hit is Weak. The bar is still useful. It flags “too short,” “only one character class,” or a qwerty keyboard run. It cannot, by itself, issue a “keep using this” certificate. The decision you usually need is two sentences: hit the list, or shorter than 8 — change it now; miss the list and long enough — still do not reuse it across sites, and write a fresh string for important accounts with a password manager or the local generator.

“A full-web lookup said it missed” is not the end either. A range query depends on what the other corpus ingested and how often it updates. Unpublished leaks, internal-system passwords, and variants that have not been hashed into that set will not appear. It is far wider than a local 860-row list, and it is still someone else’s sample. Using both tools is fine if you can tell what each one sent outbound and what a failure means.

Check Network on the spot: the wordlist may appear, the password must not

The steps below do not depend on a brand claim. Use a disposable test password — password, or a temporary string you have never used on any account. Do not paste a live password into a demo.

  1. Open DevTools Network and turn on Preserve log. Filter Fetch / XHR first, then scan documents and other requests.
  2. Reload the check page. You should see a static list (on this site, leaked-top10k.txt). Open that request: the response is one password per line, and the request body should be empty.
  3. Type the test password in the input box and wait for a result. Inspect any new requests: the URL, query, JSON, and form fields must not contain the string you just typed.
  4. Search the panel for pwnedpasswords, hibp, and range/. A local-list design should not hit those hosts. If it does, the page ran a range query — read the previous section instead of treating it as “fully local.”
  5. Scan analytics requests (paths often include matomo or collect). Event names may say Weak / Medium / Strong. Values must not include the password.
  6. To compare a full-corpus design, run the same disposable password on a page that calls HIBP. You should see a GET to api.pwnedpasswords.com/range/ whose path is five hex characters and nothing else.

Disconnect the network and type once more. That is a useful extra check for a local design: if the wordlist is already cached, strength and list hits should still compute; a range query should fail. Do not treat “zero requests” as the only passing grade — the first visit has to fetch the wordlist, and that is not the same traffic as POSTing the password. The previous article used the same panel for local encryption. Here you watch one extra thing: whether any business request carries your input.

Common mistakes: green bars, “the whole web,” and “I already checked”

“The bar is green, so it has not leaked” does not hold. Green describes character space. A leak describes whether someone else already holds the same string. Both can be true at once.

“It says local computation, so nothing left the tab” also does not hold. A local list downloads a wordlist. A range query downloads a hash bucket. What you want to forbid is the original — and the full hash — leaving as business data. You do not need to forbid every HTTP request.

“It did not appear in HIBP, so I can reuse it on every site” is the expensive mistake. Credential stuffing tries one password against many sites. It does not require that password to sit in the public top thousand. Neither a local list nor a full-corpus lookup fixes reuse. Generate a new password on this device, use the random default of 16 characters or longer, and store a different string per site.

Pasting a password into chat so a coworker can “see if it is strong” turns a check into a leak. When you must hand a new password to someone else, put a short secret on a one-time link and keep the key after # in the URL. A file you will decrypt more than once belongs in the file encryption box. The check page answers “look at the list and the bar yourself.” It is not a key-exchange channel.

Where to start

Start with a password you already plan to retire, or one that has never been used on a real account. Open the check page, watch the wordlist request in Network, type, then confirm the string did not leave. If it hits the list, do not keep two characters and reuse it. Open the password generator and create one on this device, length 16 or more. A miss only means it is not a member of this public weak-password set. Still store a different password per site.

If the question you actually have is “has this password appeared in a known large dump,” about 860 local rows are not enough. Use a tool that runs a k-anonymity range query, and confirm in Network that only a 5-character prefix left. Do not hand the original to an unknown lookup page. After both checks, remember: a tool that opens without signup does not replace each site’s own login protection, and it cannot prove a server will never leak later.

Once you have done that, you can already answer the title. A local leaked-password list proves “does this look like the batch attackers try first.” A full-web password lookup — if it is implemented correctly — proves “does the full hash appear in the corpus they maintain.” The first sends a wordlist out and keeps the password in. The second sends a prefix out and keeps the original in. A third design that POSTs the original belongs to neither.

FAQ

If the local list misses, should I still check Have I Been Pwned?

It depends which sentence you need. A miss only means the string is not on this public weak-password list. If you also want to know whether it appears in HIBP’s password-hash corpus, run a separate range query and confirm in Network that only a 5-character prefix left. Keep the two checks apart. Do not collapse them into “I already searched the whole web.”

Does a range query tell HIBP my password?

Under the official design and Troy Hunt’s write-up, the other side receives the first five characters of a SHA-1 or NTLM hash — not the password, and not the full hash. Matching finishes in your browser. It is still an outbound request. If you will not let any prefix leave the device, use only the local list and accept the narrower coverage.

Do I need an account to check a password? Is the candidate uploaded?

No account. On a local design, the candidate should stay in the input box. What may leave is the wordlist file, plus analytics events that do not contain the original. Whether a page actually does that is a Network question, not a “we never upload” line on the page.

Can I trust “offline crack time: N years” on the strength bar?

That figure is an order-of-magnitude hint at a fixed guess rate. It is not a measurement of a particular GPU or a wordlist attack. When the list hits, attackers will not walk that clock. Treat it as a reminder that the string is short or uses too few character classes — not as a safety guarantee.