# What Information Is Passed to an Async Module Function in Holehe?

> Learn what information async module functions receive in Holehe. Discover how to use the target email, aiohttp session, and results list effectively for your checks.

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

---

**Every async module function in Holehe receives three arguments: the target email string, a shared `aiohttp.ClientSession` instance, and a mutable results list for collecting output.**

Holehe is an open-source email investigation framework developed by megadose that verifies address existence across hundreds of online services. Understanding what information is passed to an async module function in Holehe is critical for developers extending the tool or analyzing its enumeration capabilities. The codebase enforces a strict uniform interface across all service modules, enabling the core runner to orchestrate parallel checks while maintaining consistent data contracts.

## The Standard Three-Parameter Signature

Every service-specific checker in Holehe implements an identical asynchronous function signature. You can see this pattern in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py) and [`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py):

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

```

This consistent interface allows the orchestration logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to invoke dozens of modules concurrently without requiring service-specific handling logic.

### The `email` Parameter

The `email` parameter is a Python string containing the address being investigated. Modules use this value to construct registration validation requests against their target platforms. For instance, when checking Twitter, the module passes this email to Twitter's registration availability endpoints to determine if an account exists.

### The `client` Parameter

The `client` parameter is an `aiohttp.ClientSession` instance created once in the core runner and shared across all modules. This asynchronous HTTP client enables non-blocking web requests throughout the checking process. The session configuration, including user-agent strings defined in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py), is applied globally to maintain consistent request signatures and connection pooling across hundreds of simultaneous checks.

### The `out` Parameter

The `out` parameter is a mutable Python list that serves as a concurrent result collector. Each module appends a standardized dictionary to this shared list rather than returning values directly. This design pattern eliminates the need for complex synchronization primitives while allowing `asyncio.gather()` to aggregate results from all parallel checks into a single collection.

## The Result Dictionary Structure

Every module appends a dictionary with specific schema fields to the `out` list. As implemented in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py), the structure contains:

- **`name`**: Human-readable service identifier (e.g., "twitter")
- **`domain`**: The service domain (e.g., "twitter.com")
- **`method`**: Verification method employed (typically "register")
- **`frequent_rate_limit`**: Boolean indicating whether the service applies strict rate-limiting policies
- **`rateLimit`**: Boolean set to `True` if the current request encountered a rate limit
- **`exists`**: Boolean indicating whether the email is registered on the service
- **`emailrecovery`**, **`phoneNumber`**, **`others`**: Optional metadata fields usually defaulting to `None`

## Implementation Examples from the Source Code

### Calling a Module Directly

You can invoke individual modules for testing or targeted service checks:

```python
import aiohttp
from holehe.modules.social_media import twitter

async def run_one_check():
    async with aiohttp.ClientSession() as client:
        results = []
        await twitter("example@example.com", client, results)
        print(results)
        # Output: [{'name': 'twitter', 'domain': 'twitter.com', ...}]

```

### Core Orchestration Pattern

The [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) file demonstrates how the framework leverages the uniform signature to execute parallel checks:

```python
import asyncio
import aiohttp
from holehe.modules import social_media, software

async def run_all(email):
    async with aiohttp.ClientSession() as client:
        out = []
        # Collect all async functions from module packages

        tasks = [
            func(email, client, out)
            for func in [
                social_media.twitter.twitter,
                social_media.facebook.facebook,
                software.office365.office365,
                # ... additional modules

            ]
        ]
        await asyncio.gather(*tasks)
        return out

```

This pattern creates coroutine tasks for each module function, passing identical argument positions to each, then executes them concurrently using `asyncio.gather()`.

## Key Source Files in the Repository

The implementation of this async interface spans several critical files in the megadose/holehe repository:

- **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)**: Orchestrates asynchronous execution, instantiates the shared HTTP client, and manages results aggregation.
- **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)**: Defines user-agent strings used by the shared client session to avoid detection.
- **[`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)**: Canonical example demonstrating the async signature and proper result construction.
- **[`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py)**: Alternative implementation showing the same interface for enterprise services.
- **[`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py)**: Package initializer that imports all service functions for automatic discovery by the core runner.

## Summary

- Every async module function in Holehe receives exactly three arguments: an email string, an `aiohttp.ClientSession`, and a mutable results list.
- The `email` parameter provides the target address for verification against specific services.
- The `client` parameter enables shared, non-blocking HTTP requests with consistent configuration across all parallel checks.
- The `out` parameter acts as a concurrent result collector, with modules appending standardized dictionaries containing existence status, rate limit flags, and service metadata.
- This uniform design allows [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to orchestrate hundreds of parallel service checks efficiently without module-specific invocation logic.

## Frequently Asked Questions

### What is the exact function signature required for Holehe async modules?

Every service module must implement `async def <service_name>(email, client, out)`. This three-parameter signature is enforced across all files in the `holehe/modules/` directory, from social media checkers to enterprise software validators. The core runner in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) depends on this consistency to invoke modules generically using positional arguments.

### Why does Holehe pass the HTTP client as a parameter rather than creating it inside each module?

Passing the `aiohttp.ClientSession` as the `client` parameter allows the core runner to maintain a single session with shared connection pooling and configuration. This approach, defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), reduces TCP connection overhead and ensures consistent request headers—including the user-agent from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)—across all simultaneous checks performed by the async modules.

### What happens if a module fails to append to the `out` list?

If a module does not append its result dictionary to the `out` list, that service check produces no output in the final aggregation. The mutable list design requires explicit appends; otherwise, the check effectively disappears from results. The standard pattern shown in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py) ensures every code path appends a result, including error states and rate limit detections.

### Can custom modules use different parameter names or accept additional arguments?

No, custom modules must adhere strictly to the `(email, client, out)` signature. The core orchestration logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) discovers and calls modules using positional arguments based on this contract. Adding extra parameters or altering names would break the generic invocation pattern used by `asyncio.gather()` in the main execution loop, causing runtime errors during parallel processing.