# How the Holehe Login Detection Method Works: Email Verification via Simulated Authentication

> Learn how Holehe's login detection method verifies email registration by simulating logins and analyzing responses, not by using passwords.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: internals
- Published: 2026-08-23

---

**Holehe detects email registration status by simulating login attempts against target services, analyzing HTTP responses and JSON payloads to determine account existence without requiring valid passwords.**

Holehe is an open-source email investigation framework developed by **megadose/holehe** that verifies whether an email address is registered across hundreds of web services. The **Login detection method** serves as the primary mechanism for this verification, implementing service-specific authentication flows that attempt to access accounts using the target email address. This approach standardizes email verification across diverse platforms while handling the unique anti-CSRF protections, token requirements, and response formats of each individual service.

## The Four-Step Login Detection Pattern

Every Holehe module implementing the Login detection method follows a consistent asynchronous pattern defined in individual service modules. The workflow operates through four distinct phases:

1. **Token and Session Acquisition** – Modules fetch initial pages to extract anti-CSRF tokens, XSRF headers, or client identifiers required by the target service.
2. **Request Construction** – Builders assemble HTTP POST (or occasionally GET) requests to authentication endpoints, embedding the target email address and minimal dummy data.
3. **Authentication Attempt** – The module sends the request via `httpx.AsyncClient`, simulating a legitimate login attempt.
4. **Response Analysis** – Code interprets HTTP status codes, JSON payloads, or redirect behaviors to determine if the email is registered.

All Login method modules set `method = "login"` and return a standardized dictionary containing `exists`, `rateLimit`, `emailrecovery`, and other metadata.

## Core Orchestration in holehe/core.py

The central execution engine resides in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), which schedules each module's async function through `launch_module()`. This orchestrator manages the `httpx.AsyncClient` instance passed to every module, collects the standardized result dictionaries, and handles concurrent execution across multiple services.

Modules do not implement detection logic in the core file; instead, [`core.py`](https://github.com/megadose/holehe/blob/main/core.py) acts as the dispatcher. Each service-specific module implements its own login routine while adhering to the output contract: returning a dictionary with keys including `name`, `domain`, `method`, `exists`, `rateLimit`, `frequent_rate_limit`, `emailrecovery`, `phoneNumber`, and `others`.

## Implementation Examples

### Snapchat Login Detection (holehe/modules/social_media/snapchat.py)

The Snapchat module demonstrates complex token extraction and JSON-based existence verification. Located at [`holehe/modules/social_media/snapchat.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/snapchat.py), this implementation first harvests security tokens from the login page HTML before attempting authentication:

```python
async def snapchat(email, client, out):
    name = "snapchat"
    domain = "snapchat.com"
    method = "login"
    frequent_rate_limit=False

    # 1. Fetch the login page to obtain X-SRF token & client-id

    req = await client.get("https://accounts.snapchat.com")
    xsrf = req.text.split('data-xsrf="')[1].split('"')[0]
    webClientId = req.text.split('ata-web-client-id="')[1].split('"')[0]

    # 2. Build the login request

    url = "https://accounts.snapchat.com/accounts/merlin/login"
    headers = {
        "Host": "accounts.snapchat.com",
        "User-Agent": random.choice(ua["browsers"]["firefox"]),
        "Accept": "*/*",
        "X-XSRF-TOKEN": xsrf,
        "Accept-Encoding": "gzip, late",
        "Content-Type": "application/json",
        "Connection": "close",
        "Cookie": f"xsrf_token={xsrf}; web_client_id={webClientId}"
    }
    data = '{"email":' + email + ',"app":"BITMOJI_APP"}'

    # 3. Send the request

    response = await client.post(url, data=data, headers=headers)

    # 4. Analyse the response

    try:
        if response.status_code != 204:
            data = response.json()
            out.append({
                "name": name, "domain": domain, "method": method,
                "frequent_rate_limit": frequent_rate_limit,
                "rateLimit": False,
                "exists": data["hasSnapchat"],
                "emailrecovery": None,
                "phoneNumber": None,
                "others": None})
            return None
        out.append({"name": name, "domain": domain, "method": method,
                    "frequent_rate_limit": frequent_rate_limit,
                    "rateLimit": False, "exists": False,
                    "emailrecovery": None, "phoneNumber": None, "others": None})
    except Exception:
        out.append({"name": name, "domain": domain, "method": method,
                    "frequent_rate_limit": frequent_rate_limit,
                    "rateLimit": True, "exists": False,
                    "emailrecovery": None, "phoneNumber": None,
                    "others": None})

```

This module specifically checks for HTTP status code **204** (indicating successful login, which implies the account exists) versus other status codes that return JSON containing the `hasSnapchat` boolean flag.

### Evernote Login Detection (holehe/modules/productivity/evernote.py)

The Evernote module in [`holehe/modules/productivity/evernote.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/productivity/evernote.py) illustrates a classic form-based login flow that examines JSON responses for account existence markers:

```python
async def evernote(email, client, out):
    name = "evernote"
    domain = "evernote.com"
    method = "login"
    frequent_rate_limit=False

    headers = {"Referer": "https://www.evernote.com/Login.action"}
    # 1. Initial GET to obtain hidden form fields

    data = await client.get("https://www.evernote.com/Login.action", headers=headers)

    # 2. Build payload for the login POST

    data2 = {
        "username": email,
        "analyticsLoginOrigin": "login_action",
        "clipperFlow": "false",
        # other mandatory fields …

    }
    # 3. POST login request

    response = await client.post('https://www.evernote.com/Login.action',
                                 data=data2, headers=headers)

    # 4. Interpret response – Evernote returns JSON with "hasEvernote" flag

    result = response.json()
    out.append({
        "name": name, "domain": domain, "method": method,
        "frequent_rate_limit": frequent_rate_limit,
        "rateLimit": False,
        "exists": result.get("hasEvernote", False),
        "emailrecovery": None, "phoneNumber": None, "others": None})

```

Unlike Snapchat's token-heavy approach, Evernote relies on standard form POST data but similarly extracts the `hasEvernote` boolean from the JSON response to determine registration status.

## Response Interpretation and Rate Limiting

Holehe's Login detection method interprets server responses through three primary indicators:

- **Success Indicators**: HTTP 200/204 status codes or JSON boolean flags (`hasSnapchat`, `hasEvernote`, `hasPatreon`) set to `true` indicate the email is registered.
- **Failure Indicators**: Error messages stating "invalid credentials", "password too short", or specific JSON error codes (such as code 2 for "User already exists" in some services) confirm non-existence.
- **Rate Limiting**: HTTP 429 responses or connection failures trigger the `rateLimit: True` flag in the output dictionary, allowing the Holehe interface to display "[x]" for that service.

Additional implementations in [`holehe/modules/social_media/patreon.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/patreon.py) and [`holehe/modules/shopping/amazon.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/amazon.py) follow this same pattern, using direct POST requests to `/login` endpoints and parsing specific JSON error codes or existence flags to determine registration status.

## Summary

- The **Holehe Login detection method** simulates authentication attempts to verify email registration without requiring valid passwords.
- Each module sets `method = "login"` and implements a standardized async function signature accepting `email`, `client`, and `out` parameters.
- Detection relies on parsing HTTP status codes, JSON response flags, and error messages to set the `exists` boolean in the output dictionary.
- Anti-CSRF tokens and session identifiers are extracted from preliminary GET requests to satisfy service-specific security requirements.
- The core orchestrator in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) handles concurrent execution while individual modules contain the service-specific login logic.
- Rate limiting detection (HTTP 429) prevents false negatives and marks services as temporarily unavailable.

## Frequently Asked Questions

### How does Holehe distinguish between registered and unregistered emails?

Holehe analyzes the HTTP response status and payload returned by the login endpoint. Services typically return distinct JSON flags (like `hasSnapchat`, `hasEvernote`, or `hasPatreon`) or specific error codes indicating "user already exists" versus "invalid credentials" or "account not found". The Login detection method captures these nuances through service-specific parsing logic in each module.

### Why does Holehe use a dummy password instead of trying to crack the actual password?

The Login detection method intentionally uses placeholder or minimal data (often just the email and a dummy password) because the goal is presence detection, not authentication. Most services reveal whether an email is registered during the initial validation phase before password verification occurs, allowing Holehe to determine account existence without attempting unauthorized access.

### What happens when a service rate-limits the Login detection attempt?

When a module encounters HTTP 429 responses or connection timeouts, it catches the exception and appends a result dictionary with `rateLimit: True` to the output list. This signals to the Holehe interface that the service is temporarily blocking requests, displaying "[x]" rather than a true/false existence value, allowing users to retry later.

### Can the Login detection method bypass two-factor authentication protections?

No. The Login detection method operates at the initial authentication stage, submitting only the email address (and occasionally dummy credentials) to the login endpoint. It detects whether the account exists based on the service's response to this initial submission, before any two-factor or multi-factor authentication challenges would occur.