# Holehe Async Module Function Signature: The Standardized API for Email OSINT

> Discover the standardized Holehe async module function signature async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None. Streamline email OSINT checks across 60+ services.

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

---

**Every asynchronous module function in the Holehe repository follows the exact signature `async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None`, enabling uniform email existence checks across 60+ services.**

Holehe is an open-source OSINT tool that checks where an email address is registered online. Its architecture relies on a modular design where each service interrogator lives in its own Python file under `holehe/modules/`. To allow the core runner to execute dozens of checks concurrently without custom logic for each site, every module exposes an identical asynchronous function signature.

## The Universal Three-Parameter Pattern

According to the source code in `megadose/holehe`, all public module functions implement this strict interface:

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

```

The parameters serve distinct roles:

- **`email`** – The target address to probe, passed as a standard Python string.
- **`client`** – An `httpx.AsyncClient` (or compatible) instance, typically pre-configured with random user-agents from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) and optional proxy settings.
- **`out`** – A mutable list passed by reference that the function appends a result dictionary to. This dictionary contains keys such as `name`, `domain`, `method`, `exists`, `rateLimit`, and `error`.

This signature appears consistently across all module categories, from social media scanners in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py) to shopping platforms in [`holehe/modules/shopping/amazon.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/amazon.py).

## Module Categories and File Structure

The repository organizes modules into 20 functional categories. While each file contains unique logic for bypassing CSRF tokens or parsing JSON responses, the function signature remains invariant.

### Social Media and Communication

Services checking major platforms follow the standard signature:

- **[`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)**: `async def twitter(email, client, out)`
- **[`holehe/modules/social_media/instagram.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/instagram.py)**: `async def instagram(email, client, out)`
- **[`holehe/modules/social_media/discord.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/discord.py)**: `async def discord(email, client, out)`
- **[`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py)**: `async def facebook(email, client, out)`

### Software and Development

Programming-related services use the same interface:

- **[`holehe/modules/programing/github.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/programing/github.py)**: `async def github(email, client, out)`
- **[`holehe/modules/programing/replit.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/programing/replit.py)**: `async def replit(email, client, out)`
- **[`holehe/modules/programing/codecademy.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/programing/codecademy.py)**: `async def codecademy(email, client, out)`
- **[`holehe/modules/software/docker.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/docker.py)**: `async def docker(email, client, out)`
- **[`holehe/modules/software/adobe.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py)**: `async def adobe(email, client, out)`

### Shopping and E-commerce

Commercial platforms adhere to the pattern:

- **[`holehe/modules/shopping/amazon.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/amazon.py)**: `async def amazon(email, client, out)`
- **[`holehe/modules/shopping/ebay.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/ebay.py)**: `async def ebay(email, client, out)`
- **[`holehe/modules/shopping/deliveroo.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/deliveroo.py)**: `async def deliveroo(email, client, out)`

### Additional Categories

The uniform signature extends to niche categories including:

- **Music**: `spotify`, `soundcloud`, `lastfm` in `holehe/modules/music/`
- **Productivity**: `evernote`, `anydo` in `holehe/modules/productivity/`
- **Medical**: `caringbridge`, `sevencups` in `holehe/modules/medical/`
- **Payment**: `venmo` in [`holehe/modules/payment/venmo.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/payment/venmo.py)

## Internal Helper Functions vs. Public API

While the public-facing module functions maintain the strict three-parameter contract, some modules define **internal async helpers** with extended signatures for multi-step authentication flows. For example, [`holehe/modules/products/samsung.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/products/samsung.py) contains `get_phone_number`, which accepts additional `cookies` and `headers` parameters. These helpers are implementation details used within the file and are **not** called by the core runner.

## How [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) Leverages the Signature

The uniformity of the async module function signature enables the orchestration logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to discover and execute modules dynamically. The runner introspects the `holehe/modules/` directory, imports each function, and schedules concurrent tasks using `asyncio.gather()` without branching logic:

```python

# Conceptual flow from holehe/core.py

tasks = []
for module_function in discovered_modules:
    tasks.append(module_function(email, client, results_list))
await asyncio.gather(*tasks)

```

Because every function accepts `client` and `out` identically, the core engine shares a single `httpx.AsyncClient` instance across all checks and aggregates results into a single list efficiently.

## Practical Example: Direct Module Invocation

You can import and call any module function directly when building custom workflows, provided you supply the three required arguments:

```python
import httpx
import asyncio
from holehe.modules.social_media.twitter import twitter

async def check_twitter():
    async with httpx.AsyncClient() as client:
        results = []
        await twitter("target@example.com", client, results)
        # results now contains: [{'name': 'twitter', 'exists': True/False, ...}]

        print(results)

asyncio.run(check_twitter())

```

This pattern works identically for any module in the repository, from [`holehe/modules/mails/google.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/mails/google.py) to [`holehe/modules/porn/pornhub.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/porn/pornhub.py).

## Summary

- **Standard signature**: All async module functions use `async def func(email, client, out)`.
- **Location**: Modules reside in categorized subdirectories under `holehe/modules/`.
- **Parameters**: `email` (str), `client` (httpx.AsyncClient), and `out` (list).
- **Return value**: `None`; results are appended to the mutable `out` list.
- **Internal helpers**: Some modules define private functions with extra parameters, but these are not part of the public API consumed by [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py).

## Frequently Asked Questions

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

Every module exposes `async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None`. This signature is enforced across all 60+ services, allowing the core runner to invoke each function without custom adapters.

### Why does Holehe use a mutable list instead of returning values?

The `out` list parameter enables safe concurrent aggregation. When `asyncio.gather()` runs dozens of module functions simultaneously, each appends its result dictionary to the shared list without race conditions, avoiding the need for complex return-value collation logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py).

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

The type hint specifies `httpx.AsyncClient`, but any compatible async client implementing `.get()`, `.post()`, and similar coroutine methods will work, provided it supports the same interface. However, the official `holehe` distribution pre-configures `httpx.AsyncClient` instances with randomized user-agents from [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py).

### How do I add a custom module to Holehe?

Create a Python file in the appropriate `holehe/modules/<category>/` subdirectory. Define an async function matching the standard signature `(email, client, out)`, append your result dictionary to `out`, and ensure the function name matches the service identifier. The auto-discovery mechanism in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) will include it automatically on the next run.