# How to Use Holehe as a Python Library in Your Applications

> Integrate Holehe's email OSINT into your Python apps. Import core utilities to run async checks against 120+ services, bypassing the CLI for seamless application embedding.

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

---

**You can embed Holehe's email OSINT capabilities directly into Python applications by importing `holehe.core` and utilizing the `import_submodules`, `get_functions`, and `launch_module` utilities to execute asynchronous checks against 120+ services without invoking the CLI.**

Holehe is architected as a pure-Python package within the `megadose/holehe` repository, designed for programmatic integration beyond its command-line interface. The library exposes its internal workflow engine through [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), allowing developers to perform in-process email verification using standard asynchronous patterns. By leveraging these internal APIs, you can incorporate email reconnaissance into web applications, automation frameworks, or data processing pipelines while maintaining full control over execution flow and result handling.

## Core Library Architecture

The programmatic interface centers on three orchestration utilities defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). **`import_submodules`** and **`get_functions`** (lines 37-66) dynamically discover service modules and transform them into callable async functions that accept `(email, client, out)` arguments. **`launch_module`** (lines 66-79) executes these functions within a `trio` nursery, handling exceptions and standardizing outputs into dictionaries containing keys such as `name`, `domain`, `exists`, `emailrecovery`, `phoneNumber`, and `others`.

## Installation and Dependencies

Install the package via pip to access the library components. According to [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py), Holehe requires `httpx` for asynchronous HTTP requests, `trio` for structured concurrency, `beautifulsoup4` for HTML parsing, and `termcolor` for terminal output formatting.

```bash
pip install holehe

```

## Loading Service Modules Dynamically

Unlike static imports, Holehe uses dynamic module discovery to load its extensive collection of service implementations from the `holehe/modules/` directory. The `import_submodules` function accepts the string `"holehe.modules"` as an argument and recursively imports every service definition (e.g., `holehe.modules.social_media.twitter`, `holehe.modules.software.lastpass`).

```python
from holehe.core import import_submodules

# Load all available service modules

modules = import_submodules("holehe.modules")

```

## Selecting and Executing Services

After loading modules, `get_functions(modules, args)` extracts the callable service functions, with optional filtering via the `args` parameter. Each service function follows the signature `(email: str, client: httpx.AsyncClient, out: list)`, accepting the target email, an HTTP client instance, and a shared results list.

```python
from holehe.core import get_functions
import httpx

# Extract callable functions from loaded modules

services = get_functions(modules)

# Initialize async HTTP client

client = httpx.AsyncClient(timeout=10)

```

## Implementation Examples

The following patterns demonstrate how to integrate Holehe into different application architectures using the core utilities.

### Full Asynchronous Scan

This example loads all modules and executes them concurrently using `trio`, gathering results into a standardized list.

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

async def scan_email(email: str):
    modules = import_submodules("holehe.modules")
    services = get_functions(modules)
    client = httpx.AsyncClient(timeout=10)
    results = []

    async with trio.open_nursery() as nursery:
        for service in services:
            nursery.start_soon(launch_module, service, email, client, results)

    await client.aclose()
    return sorted(results, key=lambda x: x["name"])

if __name__ == "__main__":
    data = trio.run(scan_email, "target@example.com")
    for entry in data:
        print(entry)

```

### Synchronous Wrapper for Blocking Contexts

When integrating into synchronous codebases, wrap the async logic using `asyncio.run` while maintaining the `trio` nursery internally.

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

def check_email_sync(email: str):
    modules = import_submodules("holehe.modules")
    services = get_functions(modules)
    client = httpx.AsyncClient(timeout=10)
    results = []

    async def _execute():
        async with trio.open_nursery() as nursery:
            for svc in services:
                nursery.start_soon(launch_module, svc, email, client, results)
        await client.aclose()
        return results

    return asyncio.run(_execute())

# Usage in synchronous script

if __name__ == "__main__":
    for result in check_email_sync("user@domain.com"):
        print(f"{result['name']}: {result['exists']}")

```

### Targeting Individual Services

For targeted investigations, import specific modules directly from `holehe/modules/` and invoke them through `launch_module` to maintain consistent error handling and output formatting.

```python
import httpx
import trio
from holehe.modules.social_media.twitter import twitter
from holehe.core import launch_module

async def check_twitter_only(email: str):
    async with httpx.AsyncClient() as client:
        out = []
        await launch_module(twitter, email, client, out)
        return out[0] if out else None

if __name__ == "__main__":
    result = trio.run(check_twitter_only, "specific@example.com")
    print(result)

```

## Understanding the Output Schema

Every service function populates the shared `out` list with dictionaries following a uniform schema defined in the library's core logic. Each result contains `name` (service identifier), `domain` (service domain), `exists` (boolean or None), `emailrecovery` (recovery email if exposed), `phoneNumber` (exposed phone if available), and `others` (additional metadata). The `launch_module` wrapper ensures failed requests or exceptions generate consistent output rather than crashing the nursery, making the results list safe to iterate for reporting or analysis.

## Summary

- **Import the core utilities** from [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to access `import_submodules`, `get_functions`, and `launch_module`.
- **Load modules dynamically** using `import_submodules("holehe.modules")` to discover all 120+ service implementations.
- **Execute asynchronously** via `trio.open_nursery()` to run checks concurrently with structured concurrency.
- **Standardize outputs** through the `launch_module` wrapper, which guarantees consistent dictionary keys regardless of service-specific implementations.
- **Integrate anywhere** by wrapping the async logic in `asyncio.run()` for synchronous applications or calling individual modules for targeted checks.

## Frequently Asked Questions

### Can I use standard asyncio instead of trio for running Holehe?

Yes. While Holehe's `launch_module` uses `trio.open_nursery()` internally for structured concurrency, you can wrap the execution logic in `asyncio.run()` as shown in the synchronous wrapper example. The `trio` library handles the concurrent execution internally, while your application code can use standard `asyncio` patterns to initiate the process.

### How do I limit the scan to specific services rather than loading all modules?

Pass a modules dictionary filtered by category or name to `get_functions()`. Since `import_submodules` returns a dictionary mapping module names to module objects, you can subset this dictionary before passing it to `get_functions(modules, args)` to select only specific services (e.g., only social media platforms).

### What dependencies must I manage when using Holehe programmatically?

According to [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py), Holehe requires `httpx` for HTTP requests, `trio` for async orchestration, `beautifulsoup4` for HTML parsing, and `termcolor` for output formatting. When you install via `pip install holehe`, these are automatically resolved, but you must ensure `trio` remains available for the nursery-based execution in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py).

### Is it possible to use Holehe in a completely synchronous script without async/await?

While the underlying service checks are inherently asynchronous due to I/O operations, you can encapsulate the entire async workflow in a function and execute it via `asyncio.run()` or `trio.run()` from within your synchronous code. This pattern allows the library to manage its async HTTP client and concurrency internally while presenting a blocking interface to the rest of your application.