Skip to content
Finowl

Security

Credential stuffing: how breached password checks cut takeovers

Credential stuffing reuses leaked logins at scale. Learn how it works and how breached email and password checks reduce account takeover risk in your app.

Credential stuffing is one of the most common ways accounts get taken over, and it barely involves hacking at all. Attackers take usernames and passwords leaked from one site and try them on another, betting that people reuse passwords. This post explains how the attack works, why traditional defenses struggle with it, and how breached email and password checks remove much of its fuel.

What credential stuffing is

When a service is breached, its users' email addresses and passwords often end up in circulation. Some are plaintext, some are hashes that get cracked. Over the years these leaks have been combined into enormous lists containing billions of leaked credentials.

Credential stuffing is the automated replay of those pairs against other services. An attacker loads a list of email and password combinations into a tool, points it at your login endpoint, and lets it run. Most attempts fail. A small fraction succeed, because the same person used the same password on both sites. At the scale of millions of attempts, a small fraction is a lot of accounts.

How it differs from brute force

A brute-force attack guesses many passwords for one account. A password-spraying attack tries a few common passwords across many accounts. Credential stuffing is different again: it tries one known, real password per account, the one that person actually used somewhere else. That is why it succeeds far more often than guessing and why per-account lockouts do little to stop it.

What attackers do with taken-over accounts

Once inside, attackers drain stored value, make fraudulent purchases with saved cards, harvest personal data, send spam or phishing from a trusted account, or simply resell access. Even when the direct loss is small, the support cost and loss of trust are not.

Why common defenses struggle

Each standard control helps, but none closes the gap on its own.

  • Rate limiting slows a single source, but stuffing tools rotate through large pools of IP addresses and spread attempts thinly.
  • CAPTCHAs add friction for real users and are increasingly solved by automated services.
  • Account lockouts do little because each account typically sees only one or two attempts.
  • Password complexity rules do not help at all. A leaked password that met every rule on the original site still meets them on yours.

The underlying problem is that the attacker has the right password. Controls that assume the attacker is guessing miss the point.

How breached password checks help

If the password a user sets on your site has already appeared in a breach, it is in the lists attackers use. Rejecting those passwords means a stuffing tool has nothing that works.

At signup and password change

Checking every new password against breach data is the single most direct defense. NIST SP 800-63B recommends exactly this. When a user chooses a password that is already known to attackers, you ask for a different one. The guide on blocking breached passwords at signup covers UX and code in detail.

At login

Existing accounts were created before you added the check. Checking the password at login, after it has been verified, lets you catch those. If it has since appeared in breach data, prompt the user to change it, or require it before granting full access. The login still succeeds; you are only upgrading the credential.

Finowl's password check sends only a 5-character SHA-1 hash prefix to the lookup and never logs or stores the password, so running it at login does not create a new place for secrets to leak. See how k-anonymity password checks work for the mechanics.

bash
curl -X POST https://api.finowl.co/v1/breaches/password \
  -H "Authorization: Bearer $FINOWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "password": "hunter2" }'

A breached password comes back with the number of times it has been seen. The count below is illustrative:

json
{ "breached": true, "count": 133211 }

How breached email checks help

The password check tells you whether a password is known. The email check tells you whether an address has been exposed, and in what kind of incident. Together they give you a much clearer picture of risk.

Exposure with passwords

An address that appears in a breach whose DataClasses include "Passwords" is exactly the kind of account a stuffing list will contain. That does not mean the account is compromised, but it raises the odds that an attacker holds a password this person once used.

Stealer logs and malware

Breach records flagged IsStealerLog or IsMalware come from information-stealing malware on someone's device rather than a server breach. Those records often contain the exact site, username and password the person typed, which is a sharper signal than an old database leak. The post on reading a breach record explains each flag.

Checking an address

python
import os
import requests

def email_exposure(email: str) -> dict:
    resp = requests.post(
        "https://api.finowl.co/v1/breaches/email",
        headers={
            "Authorization": f"Bearer {os.environ['FINOWL_API_KEY']}",
            "Content-Type": "application/json",
        },
        json={"email": email},
        timeout=5,
    )
    resp.raise_for_status()
    data = resp.json()

    verified = [b for b in data["breaches"] if b["IsVerified"]]
    return {
        "breached": data["breached"],
        "password_exposed": any("Passwords" in b["DataClasses"] for b in verified),
        "stealer_log": any(b["IsStealerLog"] or b["IsMalware"] for b in data["breaches"]),
    }

print(email_exposure("alex@example.com"))

Combining the signals

Neither check is a verdict on its own. Combined with what you already know about a login, they let you apply friction only where it is needed.

Signal Risk level Reasonable response
Password breached High Require a password change
Email in breach with passwords, new device Elevated Step-up verification, such as an email code
Email in stealer log High Require password change and offer two-factor
No breach signals, known device Low Normal login

Push two-factor where it matters

Two-factor authentication defeats credential stuffing because the attacker's password alone is not enough. Many users will not enable it unprompted. Showing the prompt to users whose email appears in password-exposing breaches targets the people who benefit most.

Monitor over time

New breaches surface after the fact. Re-checking customer addresses on a schedule lets you notify users when they appear in a newly added incident, ideally before attackers work through the list. The email breach monitoring guide covers scheduling and notification design.

Operational notes

Watch login patterns too

Breach checks reduce what attackers can use, but you should still watch for stuffing in progress: spikes in failed logins, many accounts failing from shared infrastructure, or login attempts for accounts that do not exist. Those signals tell you an attack is underway even when it is not succeeding.

Keep costs predictable

Each email or password check costs one credit. Checking passwords at signup and password change is low volume. Checking at login scales with traffic, so many teams check only on new devices or once per session, or cache a "checked recently" flag per account (never the password itself). Accounts get 100 free credits a month; packs on the pricing page start at 10,000 credits for $29 and never expire.

Respect rate limits

The API allows 60 requests per minute per account. Login checks should handle 429 rate_limited by failing open rather than blocking the user, and log the event so you can plan capacity.

Product details are on the password breach and email breach feature pages.

Frequently asked questions

What is the difference between credential stuffing and brute force?

Brute force guesses many passwords for one account. Credential stuffing replays real email and password pairs leaked from other sites, so each attempt has a much higher chance of working.

Does checking passwords against breach data stop credential stuffing?

It removes the passwords stuffing depends on. If no account on your site uses a known-breached password, leaked pairs from elsewhere will not work, though you should still use two-factor and monitor login patterns.

Should I check passwords at login as well as signup?

Yes, if you have existing accounts created before you added signup checks. A login check lets you prompt users to change passwords that have since appeared in breach data.

Why do stealer log records matter more than old breaches?

Stealer logs come from malware on a user's device and often contain the exact credentials typed into specific sites. They are usually more recent and more directly usable than an old database leak.

All articles