# How to Directly Import and Use a Holehe Module in Python

> Learn to directly import and use Holehe modules in Python. Execute service checkers asynchronously using httpx within your async runtime for efficient data retrieval.

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

---

**Directly import any Holehe service checker as an asynchronous function from `holehe.modules.<category>.<service>`, then execute it with an `httpx.AsyncClient` and a mutable results list inside an async runtime like Trio.**

Holehe by megadose organizes every email-vetting check as an async function within a nested package hierarchy. While the CLI handles module discovery automatically, you can bypass the command-line interface entirely and import any individual checker directly into your own Python scripts for custom automation workflows.

## Understanding the Module Structure

Holehe stores each service implementation as a standalone module under `holehe/modules/`, categorized by service type such as `social_media`, `shopping`, or `transport`. Each module exports an async function matching the service name.

For example, the Twitter checker resides in [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py) and exports the async function `twitter`. According to the source code in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 37-48), the package provides a helper called `import_submodules` to dynamically discover these modules for the CLI, but you can import them statically without touching the discovery logic.

## Importing and Running a Single Checker

To use a specific module programmatically, import the async function directly and invoke it with three required arguments: the target email string, an `httpx.AsyncClient` instance, and an empty list that the function will populate with results.

```python
import trio
import httpx

# Import the specific service function

from holehe.modules.social_media.twitter import twitter

async def check_single_service():
    email = "target@example.com"
    results = []  # Will be mutated by the checker

    
    async with httpx.AsyncClient() as client:
        await twitter(email, client, results)
    
    # results now contains a dictionary with the check outcome

    print(results)

trio.run(check_single_service)

```

The checker appends a dictionary to the supplied `results` list in-place rather than returning a value. This design pattern allows the library to aggregate data from multiple concurrent checks efficiently without complex return-value orchestration.

## Executing Multiple Modules Programmatically

You can import several checkers from the same category and iterate over them to perform batch lookups against a single email address.

```python
import trio
import httpx

# Import multiple service functions at once

from holehe.modules.social_media import twitter, instagram, github

async def batch_check():
    email = "user@example.com"
    out = []
    
    async with httpx.AsyncClient() as client:
        for service_fn in (twitter, instagram, github):
            await service_fn(email, client, out)
    
    for entry in out:
        print(entry)

trio.run(batch_check)

```

Every checker in the `holehe/modules/` directory follows this identical signature: `async def service_name(email: str, client: httpx.AsyncClient, out: list) -> None`.

## Dynamic Discovery with Core Utilities

If you prefer not to hardcode import statements for each service, leverage the same discovery mechanism the CLI uses. The `import_submodules` function defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 37-48) recursively loads all submodules under `holehe.modules`, and `get_functions` converts them into callable references.

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

async def run_all_services():
    # Dynamically load every module in the package

    modules = import_submodules("holehe.modules")
    functions = get_functions(modules)
    
    email = "scan@example.com"
    out = []
    
    async with httpx.AsyncClient() as client:
        for fn in functions:
            await fn(email, client, out)
    
    print(out)

trio.run(run_all_services)

```

This approach instantiates every available service checker without manual import statements, useful for comprehensive reconnaissance where you want to check an email against every platform supported by the library.

## Summary

- **Module Location**: Individual checkers live at `holehe.modules.<category>.<service>` (e.g., `holehe.modules.social_media.twitter`).
- **Async Requirement**: Every checker is an async coroutine requiring an `httpx.AsyncClient` for HTTP operations.
- **Results Pattern**: Pass an empty list as the third argument; the checker appends outcome dictionaries to this list in-place.
- **Discovery Helper**: Use `import_submodules` from [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) to dynamically load all modules when you need comprehensive coverage.
- **Runtime**: Execute with `trio.run()` or any asyncio-compatible event loop.

## Frequently Asked Questions

### How do I install Holehe before importing modules?

Install the package via pip to ensure all dependencies like `httpx` and `trio` are available: `pip install holehe`. This makes the `holehe` namespace importable in your Python environment and provides access to all submodules under `holehe/modules/`.

### Can I use asyncio instead of Trio to run the checkers?

Yes. The async functions in `holehe/modules/` are compatible with any asyncio-compatible runner. While the CLI uses Trio internally, you can substitute `trio.run()` with `asyncio.run()` or manually obtain an event loop if your application requires standard asyncio patterns.

### Why does the checker modify a list instead of returning a value?

The `out` list parameter serves as a mutable accumulator. This architectural choice maintains a consistent function signature across all modules while supporting concurrent execution strategies where multiple checkers write results to a shared collection without complex return-value handling.

### Where is the `import_submodules` function defined?

The dynamic module loader is implemented in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) between lines 37 and 48. This utility recursively imports all subpackages under a given namespace, which the CLI uses to build its service registry at runtime without hardcoding module paths.