# Holehe Module Signature: Standard Async Interface for Email Osint Modules

> Discover the standard async signature for Holehe modules: async def module_name(email, client, out). Learn how to integrate your own OSINT email modules effectively.

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

---

**Holehe modules follow a strict three-argument async signature: `async def module_name(email, client, out)` where `email` is the target address, `client` is an `httpx.AsyncClient` instance, and `out` is a mutable list for result dictionaries.**

Holehe is an open-source email osint (open source intelligence) tool by megadose that checks whether an email address is registered on hundreds of platforms. Its modular architecture depends on a uniform callable interface that every service-specific module must implement. Understanding this **Holehe module signature** is essential for contributors building new modules or developers integrating Holehe into their own pipelines.

## The Standard Three-Argument Signature

Every Holehe module is implemented as an **asynchronous function** with exactly three positional parameters. This contract is enforced by the core engine in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) when it discovers and invokes modules.

```python
async def <module_name>(email, client, out):

```

### Parameter Breakdown

| Parameter | Type | Purpose |
|-----------|------|---------|
| **email** | `str` | The target email address to verify on the service |
| **client** | `httpx.AsyncClient` | Async HTTP client for making web requests without blocking |
| **out** | `list` | Mutable result container; modules append their findings as dictionaries |

This signature appears identically across all modules, from [`holehe/modules/transport/blablacar.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/transport/blablacar.py) to [`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py). The core orchestrator relies on this consistency to load modules dynamically and execute them concurrently.

## Required Result Dictionary Structure

Modules append a standardized dictionary to the `out` list. According to the source code in existing modules like [`blablacar.py`](https://github.com/megadose/holehe/blob/main/blablacar.py), this dictionary must contain these keys:

- **`name`** — Internal module identifier (typically matching the function name)
- **`domain`** — Domain being probed (e.g., `blablacar.com`, `office365.com`)
- **`method`** — Interaction type: `"register"`, `"login"`, or `"other"`
- **`frequent_rate_limit`** — `bool` indicating if the service aggressively rate-limits
- **`rateLimit`** — `True` if the current request was throttled
- **`exists`** — `bool` indicating whether the email is registered on the service

Optional fields provide additional osint data:

- **`emailrecovery`** — Secondary email recovered from the service
- **`phoneNumber`** — Phone number associated with the account
- **`others`** — Service-specific metadata as a dictionary

## Implementing and Calling a Holehe Module

### Direct Module Invocation

You can import and call individual modules directly when testing or building selective checks:

```python
import asyncio
import httpx
from holehe.modules.transport.blablacar import blablacar

async def check_blablacar(email: str) -> dict:
    async with httpx.AsyncClient() as client:
        out = []
        await blablacar(email, client, out)
        return out[0]  # Single result dict for this service

result = asyncio.run(check_blablacar("example@example.com"))
print(result)

```

This pattern mirrors exactly how the core engine invokes modules, passing the same three arguments.

### Full Scanner Integration

The `run_modules` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) iterates all registered modules using this signature:

```python
import asyncio
import httpx
from holehe.core import run_modules  # Core orchestrator

async def scan_email(email: str):
    async with httpx.AsyncClient() as client:
        results = await run_modules(email, client)  # Calls each module with (email, client, out)

        for r in results:
            print(f"{r['name']}: exists={r['exists']}")

asyncio.run(scan_email("example@example.com"))

```

The core loader discovers modules via [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py), then instantiates each with the standard `email, client, out` signature.

## Key Source Files Defining the Contract

| File | Role in Module Signature |
|------|--------------------------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Implements `run_modules()` that enforces the three-argument call pattern |
| [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py) | Registers all modules for dynamic discovery |
| [`holehe/modules/transport/blablacar.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/transport/blablacar.py) | Reference implementation showing proper signature usage |
| [`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py) | Alternative module demonstrating the same interface |
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Supplies `ua` dictionary for User-Agent rotation in requests |

These files collectively establish the **Holehe module signature** as a rigid contract. Any deviation prevents proper integration with the core engine.

## Summary

- **Holehe module signature** requires exactly three arguments: `email`, `client`, and `out`
- All modules must be **async functions** to enable non-blocking concurrent execution
- Results are appended to `out` as dictionaries with mandatory keys: `name`, `domain`, `method`, `frequent_rate_limit`, `rateLimit`, and `exists`
- The core engine in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) depends on this uniformity for module discovery and orchestration
- Reference implementations in [`blablacar.py`](https://github.com/megadose/holehe/blob/main/blablacar.py) and [`office365.py`](https://github.com/megadose/holehe/blob/main/office365.py) demonstrate proper adherence to the contract

## Frequently Asked Questions

### What happens if a Holehe module doesn't follow the standard signature?

The core engine in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) will fail to invoke the module correctly. Modules are called with positional arguments `(email, client, out)`, so any deviation in parameter count or order causes a `TypeError`. The module discovery mechanism in [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py) assumes all registered functions conform to this interface.

### Can I use a different HTTP client instead of `httpx.AsyncClient`?

No. The `client` parameter is always an `httpx.AsyncClient` instance passed by the core engine. Modules rely on its specific API (`get`, `post`, `headers` manipulation). Replacing it would break compatibility with existing modules and the core runner.

### Is the `out` list strictly necessary, or can modules return values directly?

The `out` list is mandatory. Holehe's concurrent execution model uses mutable containers to collect results from multiple async tasks. Modules must append their result dictionary to `out` rather than returning values, as shown in [`blablacar.py`](https://github.com/megadose/holehe/blob/main/blablacar.py) and all other reference implementations.

### Which key in the result dictionary indicates successful account discovery?

The `exists` boolean determines whether the email is registered. A value of `True` confirms the account exists on the service; `False` means unregistered or indeterminate. This is the primary output consumers check when aggregating Holehe results across multiple services.