# How to Import All Holehe Modules for Programmatic Use: A Complete Guide

> Easily import all Holehe modules programmatically. Learn to use import_submodules and get_functions to dynamically load and access every site-checking module from the megadose/holehe repository.

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

---

**Use `import_submodules` from `holehe.core` to dynamically load every site-checking module under `holehe.modules` into a dictionary, then extract callable functions with `get_functions`.**

Holehe is an open-source OSINT tool that checks email addresses against hundreds of websites to uncover registered accounts. While the command-line interface handles most use cases, advanced integrations require programmatic access to its modular architecture. This guide shows you how to import all Holehe modules at once using the library's built-in helper functions.

## Understanding Holehe's Module Structure

Holehe organizes each site-specific check as a separate Python module nested under the `holehe.modules` package. Rather than manually importing dozens of individual modules, the codebase provides a dynamic loader that discovers and imports everything automatically.

The loading mechanism resides in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) at lines 37-47, where the `import_submodules` function implements the discovery logic using `importlib` and `pkgutil.walk_packages`.

## Importing All Modules with import_submodules

The `import_submodules` helper walks the entire package tree and returns a dictionary keyed by fully-qualified module names.

```python
from holehe.core import import_submodules

# Dynamically import every submodule under holehe.modules

all_modules = import_submodules("holehe.modules")

print(f"Loaded {len(all_modules)} modules")

# Keys look like: 'holehe.modules.social_media.instagram', etc.

```

This single call handles nested packages (like `social_media/`, `shopping/`, `programming/`) without requiring manual path enumeration.

## Extracting Callable Check Functions

Each imported module defines an async function whose name matches the final path component—`facebook`, `instagram`, `twitter`, and so on. To convert the raw module dictionary into a list of callable checks, use `get_functions`:

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

# Minimal args object mimicking CLI flags

class Args:
    nopasswordrecovery = False  # Set True to exclude password-recovery modules

    # nocolor = False

    # onlyused = False

all_modules = import_submodules("holehe.modules")
site_checks = get_functions(all_modules, Args())

print(f"Found {len(site_checks)} callable checks")

```

**`get_functions`** respects your runtime configuration:
- **`nopasswordrecovery=True`** filters out modules that only check password recovery endpoints
- Additional flags align with CLI behavior as implemented in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 105-108

## Running Checks Programmatically

Every extracted function is an **async coroutine** accepting three parameters: `email`, `httpx.AsyncClient`, and `results` list.

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

class Args:
    nopasswordrecovery = False

async def check_email(email: str):
    """Run all Holehe checks against an email address."""
    client = httpx.AsyncClient()
    results = []
    
    # Load modules and extract functions

    all_modules = import_submodules("holehe.modules")
    checks = get_functions(all_modules, Args())
    
    # Execute all checks concurrently

    await asyncio.gather(*[
        check(email, client, results) for check in checks
    ])
    
    await client.aclose()
    return results

# Run and inspect output

email = "target@example.com"
output = asyncio.run(check_email(email))

for entry in output:
    print(f"{entry['name']}: {entry['exists']} (rate: {entry.get('rateLimit', 'N/A')})")

```

Output dictionaries follow Holehe's standard schema with fields like `name`, `exists`, `emailrecovery`, `phoneNumber`, and `others`.

## Synchronous Execution Pattern

If your codebase requires synchronous execution, wrap the async logic in `asyncio.run()` or use an event loop explicitly—**do not call coroutines directly**:

```python
import asyncio
from holehe.core import import_submodules, get_functions

def run_holehe_sync(email: str):
    """Synchronous wrapper for Holehe checks."""
    async def _inner():
        client = httpx.AsyncClient()
        results = []
        modules = import_submodules("holehe.modules")
        checks = get_functions(modules, Args())
        
        for check in checks[:5]:  # Limit to first 5 for demo

            await check(email, client, results)
        
        await client.aclose()
        return results
    
    return asyncio.run(_inner())

```

## Key Source Files Reference

| File | Purpose |
|------|---------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Defines `import_submodules` (lines 37-47), `get_functions`, and CLI entry point (lines 105-108) |
| [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py) | Package marker enabling the `holehe.modules` namespace |
| [`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py) | Example site module implementing `async def facebook(...)` |
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Default User-Agent string consumed by all modules |
| [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) | Progress bar utilities for bulk operations |

## Summary

- **Use `import_submodules`** from `holehe.core` to load every module under `holehe.modules` dynamically
- **Pass `"holehe.modules"`** as the package name to traverse the complete tree
- **Extract callables with `get_functions`**, providing an args object for CLI-compatible filtering
- **Execute asynchronously** since all site checks are defined as coroutines
- **Structure results** as a shared list passed into each check function, following Holehe's internal pattern

## Frequently Asked Questions

### Can I import specific modules instead of everything?

Yes—standard Python imports work: `from holehe.modules.social_media import instagram`. However, you lose the automatic discovery that `import_submodules` provides. For selective loading without the helper, manually construct the import path and use `importlib.import_module()`.

### Why are all Holehe check functions asynchronous?

Each check performs HTTP requests to external services. Async execution allows concurrent network I/O without threading overhead. The `httpx.AsyncClient` parameter enables connection pooling and proper session management across hundreds of requests.

### How do I exclude specific site modules from loading?

The `get_functions` helper accepts runtime flags via an args object. Set `nopasswordrecovery=True` to filter modules. For custom exclusion logic, post-process the `all_modules` dictionary before calling `get_functions`, or subclass the args object with additional boolean attributes.

### What Holehe version introduced import_submodules?

`import_submodules` and `get_functions` have been core utilities since early releases, as visible in the repository's [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). These helpers power the CLI's own module loading, ensuring API stability for programmatic use.