# How to Use holehe as a Python API: Programmatic OSINT Integration

> Integrate OSINT checks into your Python projects using the holehe API. Programmatically perform 200+ site checks and get structured JSON results without subprocesses.

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

---

**You can use holehe as a Python API by importing functions from `holehe.core` and `holehe.modules` to programmatically execute the same 200+ site checks that the CLI performs, receiving structured JSON-like results without spawning subprocesses.**

The `megadose/holehe` repository is an open-source email OSINT (Open Source Intelligence) tool designed to identify account registration across hundreds of websites. While the command-line interface is the most common entry point, the codebase is structured as a Python package that allows you to use holehe as a Python API, embedding its reconnaissance engine directly into your own scripts, data pipelines, or security automation workflows.

## Core Architecture for API Usage

The library separates concerns between module discovery, HTTP client management, and execution orchestration. Understanding these layers is essential for stable programmatic integration.

### Module Discovery via `holehe.core`

According to the source code in [[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)](https://github.com/megadose/holehe/blob/master/holehe/core.py), the package exposes three critical functions for API usage:

- **`import_submodules(package)`** – Dynamically walks the `holehe.modules` package tree and imports every site-specific check function.
- **`get_functions(modules, args=None)`** – Filters the imported modules to extract only the callable check functions, returning a list of coroutines ready for execution.
- **`launch_module(module, email, client, out)`** – An async wrapper that executes a single site check, handles exceptions gracefully, and appends a standardized result dictionary to your output list.

### The Async HTTP Client

Every module in `holehe.modules` expects an `httpx.AsyncClient` instance as its second argument. The client handles all network I/O, and you should instantiate it once with your desired timeout configuration, then pass it to all concurrent checks. The library uses `httpx` rather than `requests` to support high-concurrency async patterns.

## Step-by-Step API Implementation

To use holehe as a Python API, follow this workflow based on the CLI implementation in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

1. **Import all site modules** using `import_submodules("holehe.modules")` to load the 200+ site checkers.

2. **Extract check functions** via `get_functions(modules)` to obtain a list of callable coroutines.

3. **Initialize the HTTP client** with `httpx.AsyncClient(timeout=10)` (or your preferred timeout).

4. **Execute checks concurrently** using an async nursery (the example below uses `trio`) or `asyncio.gather`, calling `launch_module` for each site function.

5. **Collect standardized results** from the mutable `out` list passed to `launch_module`, which will contain dictionaries with keys including `name`, `domain`, `exists`, `emailrecovery`, and `rateLimit`.

## Complete Working Example

Below is a self-contained implementation that demonstrates how to query an email address against all supported platforms programmatically:

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

async def check_email_osint(email: str, timeout: int = 10):
    """
    Run holehe checks against *email* using the Python API.
    Returns a list of result dictionaries.
    """
    # 1️⃣ Load all site modules from holehe.modules

    modules = import_submodules("holehe.modules")
    
    # 2️⃣ Extract the callable site functions

    websites = get_functions(modules)
    
    # 3️⃣ Prepare the async HTTP client

    client = httpx.AsyncClient(timeout=timeout)
    
    # 4️⃣ Container for results

    out = []
    
    # 5️⃣ Optional: Add progress instrumentation

    instrument = TrioProgress(len(websites))
    trio.lowlevel.add_instrument(instrument)
    
    # 6️⃣ Execute all checks concurrently

    async with trio.open_nursery() as nursery:
        for site_fn in websites:
            nursery.start_soon(launch_module, site_fn, email, client, out)
    
    # 7️⃣ Cleanup

    trio.lowlevel.remove_instrument(instrument)
    await client.aclose()
    
    # 8️⃣ Return sorted results

    return sorted(out, key=lambda x: x["name"])

# ----------------------------------------------------------------------

# Example usage

if __name__ == "__main__":
    target_email = "alice@example.com"
    results = trio.run(check_email_osint, target_email)
    
    # Display results

    for site in results:
        status = "[+]" if site["exists"] else "[-]"
        print(f"{status} {site['domain']}: Account exists = {site['exists']}")

```

## Understanding the Result Structure

Each entry in the returned list is a standardized dictionary defined in the site modules (e.g., [[`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/twitter.py)):

```python
{
    "name": "twitter",
    "domain": "twitter.com",
    "exists": True,
    "emailrecovery": None,
    "phoneNumber": None,
    "rateLimit": False,
    "error": False,
    "others": {"FullName": "Alice Smith"}
}

```

- **`exists`**: Boolean indicating whether the email is registered on the platform.
- **`emailrecovery`**: Partial email address if the site exposes recovery information.
- **`phoneNumber`**: Partial phone number if exposed by the service.
- **`rateLimit`**: True if the module detected throttling or blocking.
- **`others`**: Dictionary containing additional metadata scraped by the module (e.g., full name, profile URL).

## Key Source Files for API Developers

| File | Purpose | API Relevance |
|------|---------|---------------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Defines `import_submodules`, `get_functions`, and `launch_module`; contains the main async driver logic. | Core API entry points |
| [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py) | Package initialization that enables dynamic module loading. | Required for discovery |
| [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) | Provides `TrioProgress` for real-time progress tracking. | Optional UI enhancement |
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Supplies randomized User-Agent strings via `ua` variable. | Useful for custom HTTP clients |

## Summary

- **`holehe.core`** exposes the essential functions (`import_submodules`, `get_functions`, `launch_module`) needed to use holehe as a Python API.
- The API requires an `httpx.AsyncClient` and async execution context (`trio` or `asyncio`) to run the 200+ built-in site checks concurrently.
- Results are returned as standardized dictionaries containing `exists`, `emailrecovery`, `phoneNumber`, and `rateLimit` fields.
- You can integrate the library without CLI dependencies by importing directly from the package structure defined in `megadose/holehe`.

## Frequently Asked Questions

### Do I need to install the CLI to use the holehe Python API?

No. Once you install holehe via `pip install holehe`, you can import `holehe.core` and `holehe.modules` directly in your Python scripts. The CLI in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) is simply a wrapper around these same API functions that parses command-line arguments.

### Can I run checks against specific websites only instead of all modules?

Yes. While `get_functions(modules)` returns all available site checkers by default, you can filter the returned list before execution. Each function object has a `__module__` attribute containing the site name (e.g., `"holehe.modules.social_media.twitter"`), allowing you to whitelist or blacklist specific platforms programmatically.

### How does the API handle rate limiting and timeouts?

Each site module sets `rateLimit` to `True` in the result dictionary when it detects throttling (HTTP 429 or similar). The `httpx.AsyncClient` passed to `launch_module` controls the timeout; if a request exceeds this limit, the exception is caught and recorded in the `error` field without crashing the entire batch.

### Is the holehe Python API compatible with standard asyncio?

Yes. While the provided example uses `trio` for concurrency (matching the CLI's default behavior), the underlying site check functions are standard async coroutines. You can replace the `trio.open_nursery()` pattern with `asyncio.gather()` or `asyncio.TaskGroup` if you prefer using asyncio for your event loop.