How Holehe Checks If an Email Exists on Websites: Architecture and Implementation

Holehe determines whether an email address exists on hundreds of websites by dynamically loading site-specific async checkers and executing them concurrently using a shared HTTP client.

The open-source tool megadose/holehe automates email reconnaissance by probing 250+ online services in parallel. Unlike simple API queries, Holehe reverse-engineers each platform's registration flows, signup forms, and response patterns to infer account existence without authentication.

Core Architecture: How Holehe Processes Email Checks

Holehe's email checking pipeline follows six distinct stages, all orchestrated through holehe/core.py.

Loading Site-Specific Modules

The import_submodules("holehe.modules") function at lines 37-48 recursively walks the holehe/modules package tree and imports every Python file containing a platform-specific checker. Each module lives in a categorized subdirectory—social_media/, mails/, forum/, and others.

The get_functions() utility (lines 50-63) then extracts callable objects from these modules, building a list named websites containing all available checkers.

Managing Concurrent HTTP Requests

Holehe creates a single httpx.AsyncClient instance (lines 12-14) with configurable timeout settings. This shared client enables:

  • Connection pooling across all requests
  • TLS session reuse
  • Consistent header configuration

Using Trio for structured concurrency, a nursery spawns launch_module tasks for every site (lines 18-30). Each task receives the target email, the shared client, and a thread-safe results list (out).

Standardized Checker Interface

Every site module implements the same async signature:

async def <site_name>(email: str, client: httpx.AsyncClient, out: list) -> None

Inside each function, the checker:

  1. Sends HTTP requests (GET for tokens, POST for validation attempts)
  2. Parses responses (JSON APIs, HTML forms, cookies, status codes)
  3. Appends a standardized result dictionary to out

The three possible outcomes are:

  • exists = True — email already registered
  • exists = False — email not found on service
  • rateLimit = True — request throttled or blocked

Site-Specific Implementation: Instagram Email Check Example

The Instagram checker in holehe/modules/social_media/instagram.py demonstrates the pattern used across all modules.

Step 1: CSRF Token Retrieval


# Preliminary GET to extract anti-CSRF token from signup page

headers = {"User-Agent": random.choice(USER_AGENTS)}
r = await client.get("https://www.instagram.com/accounts/emailsignup/", headers=headers)
token = extract_csrf_from_html(r.text)

Step 2: Registration Attempt


# POST to attempt creation with target email

data = {
    "email": email,
    "username": random_username(),  # placeholder

    "password": random_password(),  # placeholder

    "enc_password": "#PWD_INSTAGRAM_BROWSER:0:",  # signals web client

}
headers["X-CSRFToken"] = token
r = await client.post(
    "https://www.instagram.com/accounts/web_create_ajax/attempt/",
    data=data,
    headers=headers
)

Step 3: Response Interpretation

json_resp = r.json()

if json_resp.get("check") and json_resp["check"].get("status") != "fail":
    errors = json_resp.get("errors", {})
    if "email" in errors:
        email_errors = errors["email"]
        if any(e.get("code") in ["email_is_taken", "email_sharing_limit"] 
               for e in email_errors):
            result = {"name": "instagram", "domain": "instagram.com", 
                      "exists": True, "emailrecovery": None, 
                      "phoneNumber": None, "others": None}
        else:
            result["exists"] = False
    else:
        result["exists"] = False
else:
    # Rate limiting or other failure

    result["rateLimit"] = True

out.append(result)

This pattern—token extraction, synthetic registration attempt, and error-code analysis—extends to all supported platforms, with URL endpoints and payload structures adapted per service.

Running Holehe: Command-Line and Programmatic Usage

CLI Execution

Check a single email against all supported sites:

holehe email@example.com

Filter to only registered accounts:

holehe email@example.com --only-used

Export structured results:

holehe email@example.com --csv output.csv

Python API Integration

import asyncio
import httpx
from holehe.core import import_submodules, get_functions, launch_module


async def check_email_custom(email: str, max_concurrent: int = 20):
    """
    Programmatically check email existence with custom concurrency limits.
    """
    # Load all available checkers

    modules = import_submodules("holehe.modules")
    sites = get_functions(modules)
    
    # Shared async HTTP client

    client = httpx.AsyncClient(timeout=15.0, headers={
        "Accept-Language": "en-US,en;q=0.9"
    })
    results = []
    
    # Concurrent execution with semaphore-controlled parallelism

    semaphore = asyncio.Semaphore(max_concurrent)
    
    async def bounded_check(site):
        async with semaphore:
            await launch_module(site, email, client, results)
    
    await asyncio.gather(*[bounded_check(s) for s in sites])
    await client.aclose()
    
    return results


# Example usage

if __name__ == "__main__":
    email = "target@example.com"
    findings = asyncio.run(check_email_custom(email))
    
    registered = [r for r in findings if r.get("exists")]
    print(f"Found {len(registered)} registered accounts:")
    for account in registered:
        print(f"  [+] {account['domain']}")

Key Source Files and Their Roles

File Responsibility
holehe/core.py Module discovery, async client management, Trio-based concurrency, result formatting and output
holehe/modules/social_media/instagram.py Instagram-specific email existence check via registration endpoint analysis
holehe/modules/mails/google.py Google account existence verification
holehe/localuseragent.py Rotating pool of realistic browser User-Agent strings
holehe/instruments.py Trio-compatible progress bar for CLI feedback

How Holehe Avoids Detection

The tool implements several anti-fingerprinting measures based on patterns found in holehe/localuseragent.py and individual modules:

  • User-Agent rotation — realistic browser signatures per request
  • Request spacing — implicit rate limiting through Trio task scheduling
  • Header authenticity — matching headers to claimed browser version
  • Token emulation — proper CSRF and session cookie handling

Summary

  • Holehe checks if an email exists by importing 250+ platform-specific async functions from holehe/modules
  • import_submodules() and get_functions() in holehe/core.py discover and load all available checkers dynamically
  • A shared httpx.AsyncClient enables efficient connection reuse across concurrent requests
  • Trio nurseries manage structured concurrency, spawning per-site tasks that populate a shared results list
  • Each checker returns a standardized dict with exists, rateLimit, or error status based on service-specific response analysis
  • Results are color-coded and exportable via CLI flags or programmatic access

Frequently Asked Questions

What makes Holehe different from simple API-based email checkers?

Holehe does not rely on official APIs or data breaches. Instead, it reverse-engineers each platform's registration flow by submitting synthetic signup requests and interpreting validation responses. This enables detection of accounts even when no public API exists for user enumeration.

How does Holehe handle rate limiting by target services?

Each site checker catches HTTP 429 responses, CAPTCHA challenges, and abnormal response patterns, setting rateLimit = True in the result. The Trio-based concurrency in holehe/core.py provides natural backpressure, and the shared httpx.AsyncClient reuses connections to minimize fingerprintable request signatures.

Can I add custom websites to Holehe's checking capability?

Yes. Create a new Python file in the appropriate holehe/modules/ subdirectory implementing async def checker_name(email, client, out). Follow the signature pattern from existing modules like holehe/modules/social_media/instagram.py, append a standardized result dictionary to out, and Holehe will automatically import it on next run.

Is Holehe's email existence checking accurate against all platforms?

Accuracy varies by platform security posture. Services with robust anti-automation measures (advanced CAPTCHA, device fingerprinting, behavioral analysis) may return rateLimit or indeterminate results. The tool performs best against platforms using traditional server-rendered forms with predictable JSON error responses.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →