Open-source project
thewhiteh4t/pwnedOrNot avatar
thewhiteh4t/pwnedOrNot

pwnedOrNot: a Have I Been Pwned lookup followed by a public dump search

OSINT Tool for Finding Passwords of Compromised Email Addresses

2,650 stars346 forksPythonMIT

At a glance

What is it?
A single-file Python script that asks the Have I Been Pwned v3 API whether an address turned up in a breach, then goes looking for that address in public password dumps.
Who is it for?
pwnedOrNot is at its best as a second opinion on one address, run from a terminal where you can read the output. It is honest about its limits in a way that more elaborate tooling is not, listing the three conditions under which a password stays missing instead of implying a search always succeeds.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two phases, and only one of them finds passwords

The README splits the work into two phases, and that split is the accurate description of what the tool does. Phase one calls the Have I Been Pwned v3 API to find out whether the address you supplied appears in any catalogued breach. Phase two searches public dumps for the password itself.

What lands on screen after phase one is metadata rather than a credential. The README lists what the tool displays from the API response: the name of the breach, the domain name, the date of the breach, fabrication status, verification status, retirement status and spam status. Seven fields, none of which is a password. Those status flags matter more than they look, because a breach that is unverified or still under fabrication tells you how much weight to put on the record.

The repository description promises an OSINT tool for finding passwords of compromised email addresses, and the second phase is where that promise is settled. It is not a search against Have I Been Pwned, which by design never returns passwords. It looks for the address in material that is already public, and the tool only finds something when a reachable dump happens to contain both the address and a password.

Installing from source, from BlackArch, or from a container

Source installation is a clone and a shell script:

bash
git clone https://github.com/thewhiteh4t/pwnedOrNot.git
cd pwnedOrNot
chmod +x install.sh
./install.sh

BlackArch users get a native package instead, which is also the only packaging path the README gives a command for:

bash
pacman -S pwnedornot

There is a container route as well:

bash
git clone https://github.com/thewhiteh4t/pwnedOrNot.git
docker build -t pon .
docker run -it pon

The `Dockerfile` at the root of the tree starts from `alpine:latest`, installs `python3`, `py3-pip` and `python3-dev`, copies the checkout into `/root/pwnedornot/`, marks `install.sh` executable and runs it. So the image is thin by design, and the dependency install happens at build time through the same script a local install uses.

Worth noticing what the tree contains: `.github/`, `Dockerfile`, `LICENSE`, `README.md`, `config.json`, `install.sh` and `pwnedornot.py`. That is the entire project. The tool is one Python script, which makes it easy to read end to end and easy to patch, and it also means there is no module structure to lean on if you wanted to call the dump logic from your own code.

Three ways to hand the script an API key

An API key is required, and the README flags this as important rather than optional. Because Have I Been Pwned moved to a paid subscription model, there is no free tier to fall back on, so the tool cannot run at all until a key exists.

Three input paths are documented. An environment variable is the least repetitive:

bash
export PWNED_API_KEY="<hibp-api-key>"

A command line flag works for one-off runs:

bash
python3 pwnedornot.py -e [email protected] -k <hibp-api-key>

And a config file keeps the key out of your shell history and your command line:

bash
nano ~/.config/pwnedornot/config.json
{
  "api_key": "<hibp-api-key>"
}

The tree also carries a `config.json` at the repository root, separate from the per-user path above. Those are two different files serving two different purposes: one ships with the checkout, the other is the location the README tells you to create. If you want a key to persist across directories, the `~/.config/pwnedornot/config.json` route is the documented one.

What the flags let you scope

The argument surface is small enough to take in one pass, and the help output in the README lists all of it: `-e` for a single address, `-f` for a file of addresses, `-s` for an output file of pwned addresses, `-d` to filter results by domain, `-b` to pull breach detail by breach name, `-n` to check breach information only and skip the dump phase, `-l` to list all pwned domains, `-c` to check whether a domain is pwned, and `-k` for the key.

Two of those deserve more attention than the rest. The `-n` flag is the polite one: it stops after the API phase, which is both faster and avoids sending addresses out to dump indexes. The `-l` and `-c` flags operate on domains rather than addresses, which is the shape of the question a domain owner actually asks.

The basic single-address call is the shortest possible form:

bash
python3 pwnedornot.py -e <email>

Long form flags are accepted alongside the short ones, so `--email` and `--file` work the same way. For a larger set the file input is the sensible route:

bash
python3 pwnedornot.py -f <file name>

Because the same output file option exists for saving pwned addresses, the intended batch shape is read a file of addresses, write the positive results out, and deal with those separately.

Why a password often stays missing

The README is unusually candid about failure, listing three factors that decide whether phase two produces anything: whether public dumps are available for the address, whether those dumps are accessible, and whether the dump actually contains a password rather than only email addresses.

The middle factor is the one that catches people out. The note that dumps sometimes get removed says the tool depends on material that can disappear without warning, which means two runs against the same address on different days can legitimately disagree. A miss is weak evidence.

The third factor is worth dwelling on too, because it explains a specific and confusing result: an address can be listed in many breaches and still produce no password at all, simply because the dumps that contain it carry addresses only.

The tool is also distributed through several security-focused Linux distributions. The README's availability table names BlackArch Linux, SecBSD and Tsurugi Linux, with install instructions covering Ubuntu, Kali Linux, Nethunter and Termux, BlackArch via pacman, and Docker. SecBSD and Tsurugi appear in the availability table without a matching command anywhere in the README, so treat that row as a claim about packaging rather than a set of tested instructions.

Packaging claims and the thin release trail

The README lists the platforms the tool was tested on: Kali Linux, BlackArch Linux, Kali Nethunter and Termux. It adds a note that Windows users are pointed at Kali Linux under WSL2 or a VM, which is a sensible suggestion given the tool shells out to the kind of tooling that a native Windows terminal handles awkwardly.

The container build is the odd one out. The `Dockerfile` targets `alpine:latest`, and Alpine is not among the four tested distributions in the README. That is not a contradiction so much as two different claims: the image builds, while the tested list covers the environments the author says were actually exercised.

Then there is the maintenance picture. The last push to the default branch, `master`, was 2026-03-28. There are no GitHub releases, so no version numbers to check, and no `CHANGELOG.md` in the tree. The README links a changelog, but it points at a repository wiki page rather than a file in the checkout, which means version history lives outside the thing you clone. Two open-issue-scale signals sit alongside that: 2,650 stars with 346 forks, and a small open issue count.

The README also carries a couple of typos in its own feature list, including a misspelled word in the sentence explaining that the tool leans on server-side feature flags. That is worth knowing for a different reason: the tools whose behaviour depends on somebody else's API are the ones most likely to rot quietly between releases, and typos are a fair proxy for how much review that copy gets.

Editorial conclusion

pwnedOrNot is at its best as a second opinion on one address, run from a terminal where you can read the output. It is honest about its limits in a way that more elaborate tooling is not, listing the three conditions under which a password stays missing instead of implying a search always succeeds. What it cannot be is a credential verification service: it searches public dumps it can reach, and the README is clear that dumps get pulled. The last commit landed on 2026-03-28, the changelog lives in a repository wiki rather than a changelog file, and there are no tagged releases, so there is no version history to lean on when something breaks. Install from source with install.sh, hand it a key through the PWNED_API_KEY environment variable, and read the breach metadata before you read too much into the dump phase.

Frequently asked questions

Is HaveIBeenPwned API free?

Not for the API itself, and this is the constraint that shapes the whole tool. The README marks an API key as required and links the Have I Been Pwned site for purchasing one. Since pwnedOrNot has no offline mode for the breach phase, the script will not complete a run without a key, whether you supply it by flag, environment variable or config file.

How to find leaked email passwords?

pwnedOrNot takes the two-stage route. It asks the Have I Been Pwned v3 API whether the address appears in a breach, then searches reachable public dumps for that address. The second stage only returns something when a dump exists, is still up, and contains a password rather than addresses alone, which is why misses happen so often.

Does pwnedOrNot need an API key even for a single address?

Yes. There is no separate free path for one-off lookups. A key can be passed with `-k`, exported as `PWNED_API_KEY`, or placed in `~/.config/pwnedornot/config.json`, and all three are documented in the README. The `-n` flag then limits the run to the breach metadata if you want to avoid the dump search.

Which platforms does pwnedOrNot run on?

The README lists Kali Linux, BlackArch Linux, Kali Nethunter and Termux as tested, and points Windows users at Kali under WSL2 or a virtual machine. There is also a Dockerfile based on `alpine:latest`, though Alpine is not in the tested list. BlackArch installs it as a package with `pacman -S pwnedornot`.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. thewhiteh4t/pwnedOrNot on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/thewhiteh4t-pwnedornot.svg)](https://hysenlabs.com/projects/thewhiteh4t-pwnedornot)