# How to Use Holehe Programmatically in Python: Async Email Reconnaissance

> Learn to use Holehe programmatically in Python. Import async check modules or call the main function for efficient email reconnaissance. Automate your security checks.

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

---

**Holehe can be used programmatically in Python by importing the asynchronous check modules from the `megadose/holehe` repository and executing them with an HTTPX client, or by calling the high-level `main()` function from `holehe.core` to replicate CLI behavior.**

Holehe is a pure-Python library designed for email reconnaissance across social media and web platforms. Unlike tools that require shell execution, Holehe exposes its internal machinery for direct Python integration, allowing security researchers to embed email existence checks directly into async workflows without spawning external processes.

## Understanding Holehe's Async Architecture

At the heart of Holehe lies an asynchronous architecture built on **Trio** and **HTTPX**. The entry point resides in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), where the `main()` function initializes the async event loop by calling `trio.run(maincore)`.

The `maincore()` function orchestrates the entire workflow: it parses arguments, instantiates an `httpx.AsyncClient`, and dynamically loads every available check module using `import_submodules("holehe.modules")`. Each module is then executed as a separate async task via `launch_module`, enabling concurrent checks against multiple platforms.

Individual check modules follow a strict contract. Each exposes an async function accepting three parameters: `email`, `client` (an HTTPX instance), and `out` (a list to collect results). For example, [`holehe/modules/social_media/snapchat.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/snapchat.py) implements `async def snapchat(email, client, out)` to query Snapchat's endpoints.

## Running Single Module Checks

For targeted investigations, you can import and execute specific modules without loading the entire library. This approach minimizes overhead when you only need to verify an email against a single platform.

### Importing Specific Check Modules

The following example demonstrates checking a single email against Snapchat using the raw module interface:

```python
import trio
import httpx
from holehe.modules.social_media.snapchat import snapchat

async def demo():
    email = "test@example.com"
    out = []
    async with httpx.AsyncClient() as client:
        await snapchat(email, client, out)
    print(out)

trio.run(demo)

```

The `out` list receives a standardized dictionary containing fields such as `name`, `exists`, `emailrecovery`, and `rateLimit`. This format remains consistent across all modules in the `holehe.modules` namespace.

## Orchestrating Full Email Scans

To execute comprehensive reconnaissance across all supported platforms, you must dynamically load the module registry and coordinate concurrent execution using Trio's nursery pattern.

### Loading and Executing All Modules

The `import_submodules()` function discovers all check modules, while `get_functions()` extracts the callable entry points. The following implementation runs every available check concurrently:

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

async def full_scan(email):
    modules = import_submodules("holehe.modules")
    websites = get_functions(modules)
    
    async with httpx.AsyncClient() as client:
        out = []
        async with trio.open_nursery() as nursery:
            for mod in websites:
                nursery.start_soon(launch_module, mod, email, client, out)
    
    return out

results = trio.run(full_scan, "test@example.com")
for result in results:
    print(result)

```

This pattern creates an `httpx.AsyncClient` session shared across all checks, then spawns each module as a separate task within a Trio nursery. The `launch_module` wrapper handles execution and appends standardized results to the shared `out` list.

## Using the High-Level CLI Wrapper

When you need behavior identical to the command-line interface without shelling out, invoke the `main()` function directly from `holehe.core`.

### Replicating CLI Behavior in Python

This approach handles argument parsing, client initialization, and result formatting automatically:

```python
from holehe.core import main

if __name__ == "__main__":
    main()

```

Calling `main()` executes `trio.run(maincore)`, which processes `sys.argv` exactly as the `holehe` console script would. This is ideal for scripting scenarios where you want the full suite of checks with standard output formatting, but need to trigger it from within a larger Python application.

## Key Source Files and Functions

Understanding these core components enables advanced customization of Holehe's behavior:

- **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)** — Contains `main()`, `maincore()`, `import_submodules()`, and `launch_module()`. This file manages module discovery, async orchestration, and the HTTP client lifecycle.

- **`holehe/modules/`** — Directory containing platform-specific implementations. Each submodule follows the `async def <name>(email, client, out)` signature.

- **[`holehe/modules/social_media/snapchat.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/snapchat.py)** — Reference implementation showing the request construction pattern and result dictionary formatting used throughout the library.

- **Result Schema** — Every module returns a dictionary with standardized keys including `name` (service identifier), `exists` (boolean), `emailrecovery` (partial email hints), and `rateLimit` (status indicator).

## Summary

- Holehe exposes a pure-Python API that eliminates the need for subprocess calls or shell interactions.
- The library uses Trio for async concurrency and HTTPX for HTTP transport, with the main orchestration logic in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py).
- Individual modules can be imported directly from `holehe.modules` for targeted checks using the `async def(email, client, out)` interface.
- Full reconnaissance scans utilize `import_submodules()` and `get_functions()` to dynamically load all checks, executed concurrently via `launch_module()` in a Trio nursery.
- The `main()` function provides a synchronous entry point that replicates CLI behavior while handling async execution internally.

## Frequently Asked Questions

### Can I run Holehe synchronously without using Trio directly?

Yes. Import and call `main()` from `holehe.core` to execute the full Holehe workflow synchronously. This function internally calls `trio.run(maincore)`, managing the event loop creation and teardown automatically while processing command-line arguments from `sys.argv`.

### What dependencies are required for programmatic usage?

Holehe requires **Trio** for asynchronous orchestration and **HTTPX** for HTTP requests. These are specified in the repository's requirements. When importing modules directly, ensure you have an active HTTPX async client to pass to the check functions.

### How do I interpret the results returned by Holehe modules?

Each module appends a dictionary to the provided `out` list containing standardized fields: `name` (the service checked), `exists` (boolean indicating account existence), `emailrecovery` (partial email hints if exposed), `phoneNumber` (masked phone if exposed), and `rateLimit` (boolean indicating throttling status).

### Is it possible to add custom check modules to Holehe?

Yes. Create a Python file in the `holehe.modules` namespace implementing the standard async signature `async def your_module(email, client, out)`. The `import_submodules()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) automatically discovers any module in this namespace, allowing `get_functions()` to include your custom checks in full scans.