# How to Use Holehe Programmatically to Check Multiple Modules: A Complete Guide

> Learn to use Holehe programmatically by importing core functions and running detection modules concurrently with Trio and httpx. A complete guide for developers.

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

---

**You can use Holehe programmatically by importing its async core functions from [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), which automatically discover all detection modules and run them concurrently with Trio and httpx.**

Holehe is an open-source OSINT tool for email account discovery across hundreds of services. While it provides a CLI, its true power lies in the Python API exposed through [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). This guide shows you how to embed Holehe in your own scripts to check single modules, run everything, or cherry-pick specific services.

## Understanding Holehe's Async Architecture

Holehe follows a lightweight **asynchronous design** built around three core concepts: dynamic module discovery, consistent coroutine signatures, and Trio-based concurrency.

### Module Discovery in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)

The function `import_submodules("holehe.modules")` walks the entire `holehe/modules/` package tree and imports every Python file. The helper `get_functions()` then extracts the public coroutine from each module—typically named after the service (e.g., `twitter`, `snapchat`)【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L37-L64】.

This means new modules added to the repository are automatically available without code changes.

### Standardized Module Interface

Every detection module implements the same async signature:

```python
async def service_name(email: str, client: httpx.AsyncClient, out: list) -> None:
    # Queries the service and appends result dict to `out`

```

The `launch_module()` wrapper in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) handles exceptions and converts them to standardized result objects, ensuring uniform output regardless of individual module failures【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L66-L78】.

### Concurrent Execution with Trio

A **Trio nursery** spawns all modules simultaneously. The `TrioProgress` instrument attaches to Trio's low-level instrumentation for progress tracking【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L16-L22】. Results are collected into a shared list, then sorted and processed【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L124-L131】.

## Running a Single Module Manually

For targeted checks, import and call any module directly. Here's the Snapchat module in action:

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

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

trio.run(demo_one)

```

Each module file lives under `holehe/modules/` by category. For example, the Twitter check is implemented in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)【/cache/repos/github.com/megadose/holehe/master/holehe/modules/social_media/twitter.py#L5-L37】.

## Running All Available Modules Automatically

To execute every discovered service concurrently, use Holehe's core orchestration:

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

async def demo_all():
    email = "test@example.com"

    # 1. Discover every detection module

    modules = import_submodules("holehe.modules")
    
    # 2. Convert to list of callable coroutines

    websites = get_functions(modules)

    client = httpx.AsyncClient()
    out = []
    
    # Optional: add progress bar

    instrument = TrioProgress(len(websites))
    trio.lowlevel.add_instrument(instrument)

    # 3. Launch all modules concurrently

    async with trio.open_nursery() as nursery:
        for website in websites:
            nursery.start_soon(launch_module, website, email, client, out)

    trio.lowlevel.remove_instrument(instrument)
    await client.aclose()
    
    # Sort results alphabetically by service name

    out = sorted(out, key=lambda i: i["name"])
    print(out)

trio.run(demo_all)

```

This pattern is exactly how Holehe's CLI operates. The `launch_module` wrapper ensures failures in one module don't crash the entire run.

## Selecting a Custom Subset of Modules

When you need specific services rather than everything, import modules individually and invoke them directly:

```python
import trio
import httpx
from holehe.modules.social_media.twitter import twitter
from holehe.modules.social_media.instagram import instagram

async def demo_subset():
    email = "test@example.com"
    out = []
    client = httpx.AsyncClient()
    
    for fn in (twitter, instagram):
        await fn(email, client, out)  # sequential execution

    
    await client.aclose()
    print(out)

trio.run(demo_subset)

```

For concurrent execution of a subset, swap the `for` loop for a Trio nursery with your chosen functions.

## Integrating Holehe Results into Pipelines

Each result dictionary contains standardized keys you can process programmatically:

- `name` — service name (e.g., "twitter")
- `domain` — service domain
- `method` — detection technique used
- `frequent_rate_limit` — boolean indicating rate-limit likelihood
- `exists` — boolean or None for account existence
- `emailrecovery` — partial recovery email if leaked
- `phoneNumber` — partial phone if leaked
- `others` — additional metadata

This structure makes Holehe ideal for feeding OSINT data into databases, SIEMs, or custom enrichment workflows.

## Key Source Files Reference

| File | Purpose |
|------|---------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Orchestrates discovery, async execution, result aggregation, and CSV export |
| `holehe/modules/*/*.py` | One file per service—each defines an async detection function |
| [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) | `TrioProgress` progress-bar implementation |
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Default User-Agent for HTTP requests |

## Summary

- **Single module**: Import directly from `holehe.modules.*` and call with `(email, client, out)`.
- **All modules**: Use `import_submodules()` and `get_functions()` from [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), then spawn with `launch_module()` in a Trio nursery.
- **Custom subset**: Import specific modules and invoke them sequentially or concurrently.
- **Shared client**: Pass one `httpx.AsyncClient` instance to all calls for connection reuse.
- **Consistent output**: Every module appends a standardized dictionary to the `out` list.

## Frequently Asked Questions

### What Python version does Holehe require?

Holehe requires Python 3.7+ due to its reliance on Trio and `httpx.AsyncClient`. The async/await syntax and low-level Trio instrumentation used in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) depend on modern Python features.

### Can I run Holehe without the progress bar?

Yes. Simply omit the `TrioProgress` instrument creation and the `add_instrument`/`remove_instrument` calls. The core functionality in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) works without any instrumentation—progress tracking is purely optional UI sugar.

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

Create a new Python file under `holehe/modules/` (in an existing or new category folder) with an async function following the signature `async def yourservice(email, client, out)`. The next time `import_submodules("holehe.modules")` runs, your module will be discovered automatically.

### Does Holehe handle rate limits automatically?

Individual modules set a `frequent_rate_limit` flag in results to warn about rate-limited services, but Holehe does not implement automatic backoff or retry logic. According to the source code in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), failed requests are caught by `launch_module()` and converted to error result objects without interrupting other modules.