# False Positives and False Negatives in Holehe Account Detection: Common Causes and Fixes

> Discover common causes for false positives and false negatives in Holehe account detection. Learn how ambiguous API responses, rate limiting, and outdated logic impact results and find effective fixes.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: deep-dive
- Published: 2026-08-25

---

**False positives and false negatives in Holehe primarily stem from ambiguous third-party API responses, aggressive rate limiting, and outdated parsing logic within individual service modules.**

Holehe is an open-source OSINT tool that determines whether an email address is registered on hundreds of online services by invoking public registration and recovery endpoints. Because the tool relies on interpreting JSON and HTML responses from external APIs—each implemented as an independent Python module—its accuracy depends heavily on how well these modules handle evolving error messages, CSRF protections, and network edge cases.

## How Holehe Detects Account Existence

The detection pipeline follows a modular architecture centered in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). Understanding this flow is essential to diagnosing why errors occur.

First, the `import_submodules` function (lines 37‑47 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) dynamically discovers and loads every module under `holehe/modules/`:

```python

# From holehe/core.py - Module discovery

import_submodules(holehe.modules)

```

Next, `launch_module` (lines 66‑74 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) executes each module asynchronously, passing the target email, an `httpx.AsyncClient` instance, and a shared result list. Inside individual modules—such as [`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py)—the code examines status codes and response bodies. A typical detection pattern looks like this:

```python

# Simplified logic from facebook.py (lines 53-62)

if check["status"] != "fail":
    if 'email' in check["errors"]:
        if check["errors"]["email"][0]["code"] == "email_is_taken":
            out.append({"exists": True, ...})

```

Each module returns a standardized dictionary containing keys like `exists`, `rateLimit`, and `error`. The central `print_result` function (lines 22‑49 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)) then displays “[+]” for positive matches, “[-]” for negatives, and “[!]” for errors.

## Common Causes of False Positives

False positives occur when Holehe reports an account exists where none does, usually due to misinterpreted response signals.

### Ambiguous "Email Already Taken" Messages

Some services return generic "email already used" messages for addresses that are deny-listed, previously released, or flagged by typo-squatting protections. When modules encounter these strings, they often set `exists: True` despite no active registration. For example, if a service blocks disposable domains with a "taken" response, the module at [`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py) may incorrectly flag the email as registered.

### Misinterpreted Password Recovery Responses

Modules utilizing password-recovery endpoints—such as [`adobe.py`](https://github.com/megadose/holehe/blob/main/adobe.py) or [`mail_ru.py`](https://github.com/megadose/holehe/blob/main/mail_ru.py)—may receive a "recovery email sent" status even for non-existent accounts. Services that do not explicitly disclose account existence often return identical success messages for both registered and unregistered emails. Holehe interprets this as confirmation, creating a false positive.

### CSRF Token and Anti-Scraping Fallbacks

Many modules require valid CSRF tokens to submit registration checks. In [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py), token extraction occurs around line 27. If this extraction fails due to HTML changes or bot detection, the module may fall back to generic error handling. When fallback logic improperly interprets anti-scraping challenges (like Cloudflare interstitials) as "account exists" signals, it appends `exists: True` to the results.

### Mishandled Rate Limit Flags

When requests are throttled, modules set `rateLimit: True` (visible in the exception handling blocks of [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py), lines 30‑36). Downstream analysis tools or automated scripts may mistakenly treat these flagged responses as positive matches rather than inconclusive results, generating false positives in aggregate reports.

## Common Causes of False Negatives

False negatives occur when Holehe fails to detect an existing account, typically due to blocked requests or changed API structures.

### Third-Party API Schema Changes

Services frequently alter their JSON response schemas. If a platform moves the `"email_is_taken"` indicator to a different field or renames error codes, hard-coded checks like those in [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py) no longer match. The module defaults to `exists: False`, missing valid registrations.

### Rate Limiting and Request Blocking

Persistent rate limiting prevents modules from reaching the registration endpoint entirely. When `launch_module` cannot complete the HTTP request, it often appends a result with `exists: False` or no result at all, effectively hiding existing accounts from the final report.

### Missing or Stale CSRF Tokens

If a module fails to fetch required tokens (e.g., due to cookie expiration or anti-bot measures), the subsequent POST request is rejected by the service. The module records `exists: False` because it never receives the "email taken" confirmation, even when the account is actually registered.

### HTML-Only Response Indicators

Some services embed "email already used" notifications in HTML banners rather than JSON responses. Modules configured to parse only JSON—common in older implementations—miss these indicators entirely, returning false negatives for valid accounts.

## Mitigation Strategies and Best Practices

While inherent limitations exist due to reliance on external services, you can minimize errors using built-in CLI flags and maintenance routines.

**Filter for Confirmed Results Only**

Use the `--only-used` flag to display only services where `exists` is explicitly `True`, removing ambiguous rate-limit entries from your view:

```bash
holehe user@example.com --only-used

```

**Disable Recovery Endpoint Checks**

To avoid false positives from password-recovery modules, use the `--no-password-recovery` flag (or equivalent implementation in your version):

```bash
holehe user@example.com --no-password-recovery

```

**Export for Manual Verification**

Export results to CSV for manual analysis of discrepancies, particularly useful when investigating patterns of false positives:

```bash
holehe user@example.com --csv output.csv

```

**Keep Modules Updated**

The `check_update` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 65‑87) ensures you have the latest module definitions. Regular updates minimize false negatives caused by outdated parsing logic:

```bash

# Update holehe to latest modules

pip install --upgrade holehe

```

**Programmatic Error Handling**

When using Holehe as a library, inspect the `rateLimit` and `error` fields before interpreting `exists`:

```python
from holehe.core import maincore
import trio
import sys

sys.argv = ["holehe", "user@example.com"]
results = trio.run(maincore)

# Filter out rate-limited services before analysis

confirmed = [r for r in results if not r.get("rateLimit") and not r.get("error")]

```

## Summary

- **False positives** typically arise from ambiguous "email taken" messages, misinterpreted password-recovery responses, and mishandled CSRF or rate-limit errors in modules like [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py).
- **False negatives** usually result from API schema changes, aggressive rate limiting, missing CSRF tokens, or HTML parsing limitations within individual service modules.
- **Mitigation** relies on using CLI flags such as `--only-used` and `--no-password-recovery`, regularly updating the tool via `check_update`, and programmatically filtering results for `rateLimit` or `error` statuses.
- The reliability of detection is ultimately tied to the accuracy of response parsing in files under `holehe/modules/`, making consistent updates essential as third-party services evolve.

## Frequently Asked Questions

### Why does Holehe report an account exists when the email is not registered?

This false positive usually occurs when a service returns generic "email already taken" messages for reasons other than active registration—such as deny-listed domains or typo-squatting protection. Modules like [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py) interpret these signals as confirmation of existence. Additionally, password-recovery endpoints in modules such as [`adobe.py`](https://github.com/megadose/holehe/blob/main/adobe.py) may return "email sent" statuses for non-existent accounts, which Holehe can misinterpret as proof of registration.

### How can I reduce false negatives when scanning for accounts?

To minimize false negatives, ensure you are running the latest version of Holehe so that module parsing logic matches current API schemas. Use the `check_update` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to verify module freshness. Additionally, avoid aggressive scanning that triggers rate limits, as throttled modules default to `exists: False`. Running scans with realistic User-Agent strings from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) can also help bypass basic anti-scraping measures that block requests.

### What causes Holehe to miss existing accounts on specific platforms?

False negatives often stem from two technical issues: outdated JSON schema checks and missing CSRF tokens. When services move error codes like `"email_is_taken"` to new response fields, hard-coded checks in modules fail to match. Similarly, if CSRF token extraction fails (as seen in the fallback logic of [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py)), the registration check request is rejected before the service can confirm the email exists, resulting in a reported negative.

### Should I trust rate-limited results in Holehe output?

No, rate-limited results should be treated as inconclusive. When a module encounters throttling or network errors, it sets `rateLimit: True` (see the exception handling in [`facebook.py`](https://github.com/megadose/holehe/blob/main/facebook.py), lines 30‑36). These entries should not be interpreted as confirmations of account existence or absence. Use the `--only-used` flag to exclude these ambiguous results from your final analysis, or implement custom filtering that checks the `rateLimit` key before processing results.