# How Holehe Checks for Email Existence on Websites: Architecture and Implementation

> Discover how Holehe checks email existence on websites. Learn about its architecture, concurrent module execution with Trio, and shared HTTP client for efficient verification.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: architecture
- Published: 2026-09-10

---

**Holehe verifies email registration status across hundreds of platforms by dynamically loading site-specific asynchronous checker modules and executing them concurrently using Trio with a shared HTTP client.**

The open-source tool `megadose/holehe` automates the process of determining whether an email address is already registered on over 250 websites. Unlike simple DNS lookups, Holehe performs live checks against each platform's registration endpoints by orchestrating a modular Python architecture that combines dynamic module loading with high-performance asynchronous I/O.

## Dynamic Module Loading System

Holehe begins its verification process by discovering and importing site-specific checker functions from the `holehe.modules` package tree.

The `import_submodules("holehe.modules")` function in `holehe/core.py:37-48` recursively walks the module directory, importing every Python file that implements a site-specific async function. Following the import phase, `get_functions()` (defined in `holehe/core.py:50-63`) extracts callable objects from these modules and stores them in a list called `websites`.

This architecture allows the tool to support over 250 distinct platforms without hardcoding individual site logic in the main execution loop. Each module adheres to a standardized signature: `async def <site>(email, client, out)`.

## Concurrent Execution with Trio and HTTPX

Once modules are loaded, Holehe initializes a single `httpx.AsyncClient` instance with configurable timeout settings (`holehe/core.py:11-14`). This shared client enables connection pooling and TLS session reuse across all concurrent requests, significantly improving performance when checking hundreds of sites.

The execution engine leverages **Trio** for structured concurrency. In `holehe/core.py:18-30`, the code opens a nursery that spawns a `launch_module` task for every site in the `websites` list. Each task receives the target email address, the shared HTTP client, and a thread-safe results list (`out`).

```python

# Conceptual flow from holehe/core.py

async with trio.open_nursery() as nursery:
    for website in websites:
        nursery.start_soon(launch_module, website, email, client, out)

```

## Site-Specific Verification Logic

Every checker module implements the same three-state logic to determine email existence. The function signature `async def <site>(email, client, out)` requires each module to send HTTP requests, parse responses, and append a dictionary with one of three outcomes to the shared `out` list:

- **exists = True**: The email is already registered on the service
- **exists = False**: The email is not found or available for registration  
- **rateLimit = True**: The service has throttled or blocked the request

### Instagram Implementation Example

The Instagram checker in [`holehe/modules/social_media/instagram.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/instagram.py) demonstrates this pattern:

1. **CSRF Token Acquisition**: Sends a GET request to retrieve a hidden CSRF token from the signup page
2. **Registration Attempt**: POSTs to `accounts/web_create_ajax/attempt/` with a random username and the target email
3. **Response Parsing**: Inspects the JSON response for `"email_is_taken"` or `"email_sharing_limit"` indicators
4. **Result Classification**: Sets `exists=True` if registration is blocked due to email reuse, or `rateLimit=True` if the response indicates throttling

Other modules follow identical architectural patterns while customizing request URLs, headers (often rotating User-Agents from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)), and parsing logic to match each service's API or web form behavior.

## Result Aggregation and Output

After all nursery tasks complete, Holehe processes the `out` list containing results from every module. The presentation layer in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) sorts these results and displays them with color-coded status symbols:

- `[+]` Green: Email exists on the platform
- `[-]` Red: Email not found (available)
- `[x]` Yellow: Rate limited or blocked
- `[!]` Error: Network or parsing failure

Users can optionally export results to CSV using the `--csv` flag, or filter output with `--only-used` to display only registered accounts.

## Practical Usage Examples

### Command-Line Interface

Run Holehe from the terminal to check a single email against all supported sites:

```bash

# Check email against all 250+ modules

holehe email@example.com

# Show only sites where email is registered

holehe email@example.com --only-used

# Export results to CSV file

holehe email@example.com --csv

```

### Programmatic Integration

Import Holehe's core functions to embed email verification in Python applications:

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

async def verify_email(email: str):
    # Load all checker modules

    modules = import_submodules("holehe.modules")
    websites = get_functions(modules)
    
    # Initialize shared async client

    client = httpx.AsyncClient(timeout=10)
    results = []
    
    # Execute checks with concurrency limiting

    async with asyncio.Semaphore(20):
        for site in websites:
            await launch_module(site, email, client, results)
    
    await client.aclose()
    return results

# Usage

if __name__ == "__main__":
    email = "test@example.com"
    output = asyncio.run(verify_email(email))
    for result in output:
        print(f"{result['domain']}: {result['exists']}")

```

## Summary

- **Holehe** checks email existence by dynamically importing 250+ site-specific modules from `holehe.modules` using `import_submodules()` and `get_functions()` in [`core.py`](https://github.com/megadose/holehe/blob/main/core.py)
- It executes checks concurrently using **Trio** nurseries and a shared `httpx.AsyncClient` for efficient connection pooling
- Each module follows a standardized async signature returning `exists`, `exists=False`, or `rateLimit` status based on HTTP response parsing
- The Instagram checker exemplifies the pattern: CSRF token retrieval, POST to registration endpoint, and JSON response inspection
- Results are aggregated in a thread-safe list and displayed with color-coded symbols (`[+]`, `[-]`, `[x]`) or exported to CSV

## Frequently Asked Questions

### How does Holehe handle rate limiting from websites?

Each site-specific module detects throttling independently by inspecting HTTP status codes, error messages, or response headers. When a service returns rate-limit indicators, the module appends `rateLimit=True` to the results list rather than `exists=True` or `exists=False`. Holehe displays these instances with a `[x]` symbol, allowing users to distinguish between "email not found" and "check blocked by service."

### Can Holehe check custom or internal websites?

While Holehe ships with 250+ pre-built checkers in `holehe/modules/`, the modular architecture supports extensions. Developers can add custom checks by creating new Python files in the modules directory that implement the `async def <site>(email, client, out)` signature, handling their specific target's CSRF tokens, form submissions, and response parsing patterns.

### Is Holehe undetectable when checking email existence?

Holehe attempts to mimic legitimate browser traffic by rotating User-Agent strings from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) and handling cookies like real web clients. However, sophisticated platforms may still detect automated requests through behavioral analysis or CAPTCHA challenges. The tool does not bypass advanced bot detection, and heavy usage may trigger IP-based rate limiting.

### What Python libraries does Holehe require for async operations?

Holehe relies on **Trio** for structured concurrency and task management, and **HTTPX** for asynchronous HTTP/1.1 and HTTP/2 requests. These dependencies enable the tool to maintain hundreds of simultaneous connections while sharing TLS sessions and connection pools across all site checks.