# Standard Output Format for Holehe Modules: Complete Developer Guide

> Learn the standard output format for Holehe modules. This guide details the nine keys used for uniform result aggregation in your OSINT checks. Understand Holehe's output structure.

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

---

**Each Holehe module appends a standardized dictionary with nine specific keys—`name`, `domain`, `method`, `frequent_rate_limit`, `rateLimit`, `exists`, `emailrecovery`, `phoneNumber`, and `others`—to a shared `out` list, enabling uniform result aggregation across all OSINT checks.**

Holehe is an asynchronous email reconnaissance tool developed by megadose that verifies account existence across hundreds of platforms. Understanding the standard output format for Holehe modules is critical for developers extending the framework or parsing results programmatically. This guide examines the exact schema enforced by the core engine and demonstrates implementation patterns using production code from the repository.

## The Standardized Dictionary Schema

Every module must conform to a strict dictionary contract when appending results. According to the `launch_module` implementation in [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py) (lines 66-71), the core engine expects dictionaries containing these exact keys:

- `name` — The service identifier (e.g., `"twitter"`, `"facebook"`).
- `domain` — The primary domain of the service (e.g., `"twitter.com"`).
- `method` — The interaction type, typically `"register"` for registration checks.
- `frequent_rate_limit` — Boolean flag indicating whether the service enforces aggressive rate limiting.
- `rateLimit` — Boolean set to `True` when the request hits a rate limit, otherwise `False`.
- `exists` — Boolean indicating whether the email is registered on the service.
- `emailrecovery` — Optional string containing a recovery email hint, or `None`.
- `phoneNumber` — Optional string containing an associated phone number, or `None`.
- `others` — Dictionary for additional metadata (e.g., full name, account creation date), or `None`.

This schema ensures that the aggregation logic in `print_result` and `export_csv` functions can process outputs from any module without service-specific parsing.

## Core Module Execution Logic

The [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py) file orchestrates module discovery and execution. The `import_submodules` function (lines 36-47) dynamically loads every Python file placed in `holehe/modules/`, while `launch_module` invokes each check asynchronously.

The `out` parameter is a Python list passed by reference to all concurrent modules. Because Holehe uses `asyncio` to run checks in parallel, the shared list accumulates standardized dictionaries from hundreds of sources simultaneously. The core engine then iterates over this list to generate CLI tables or CSV exports, relying entirely on the consistent key structure described above.

## Reference Implementations from Production Modules

### Twitter Module Pattern

The [twitter.py](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/twitter.py) module (lines 17-31) provides a minimal yet complete implementation. After querying Twitter's registration endpoint, it constructs the dictionary with all required keys, setting `exists` based on the HTTP response status and `rateLimit` to `False` unless the request encounters throttling.

### Facebook Module Complexity

The [facebook.py](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/facebook.py) module (lines 30-82) demonstrates advanced usage involving CSRF token extraction and session management. Despite the complex authentication flow, it maintains the identical output structure, proving that the standard format accommodates varied API interaction patterns while preserving consistency for the core aggregator.

## Creating Custom Modules

To build a compatible module, define an asynchronous function accepting three parameters: `email`, `client` (an HTTPX AsyncClient), and `out` (the shared results list).

```python

# mycustomservice.py

import httpx

async def mycustomservice(email, client, out):
    name = "mycustomservice"
    domain = "example.com"
    method = "register"
    frequent_rate_limit = False
    
    try:
        response = await client.get(
            f"https://{domain}/api/check",
            params={"email": email},
            timeout=10
        )
        exists = response.json().get("registered", False)
        
        out.append({
            "name": name,
            "domain": domain,
            "method": method,
            "frequent_rate_limit": frequent_rate_limit,
            "rateLimit": False,
            "exists": exists,
            "emailrecovery": None,
            "phoneNumber": None,
            "others": None
        })
    except httpx.HTTPStatusError:
        out.append({
            "name": name,
            "domain": domain,
            "method": method,
            "frequent_rate_limit": frequent_rate_limit,
            "rateLimit": True,
            "exists": False,
            "emailrecovery": None,
            "phoneNumber": None,
            "others": None
        })

```

Place this file in `holehe/modules/social_media/` to enable automatic discovery by the `import_submodules` loader.

## Command-Line and Programmatic Usage

Invoke Holehe via CLI to observe the standardized output:

```bash
holehe target@example.com

```

For programmatic integration, import the core launcher directly:

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

async def check_single():
    async with httpx.AsyncClient() as client:
        results = []
        await launch_module(twitter.twitter, "user@example.com", client, results)
        
        for entry in results:
            if entry["exists"]:
                print(f"Found on {entry['name']}: {entry['domain']}")

asyncio.run(check_single())

```

The `results` list contains dictionaries adhering strictly to the nine-key schema, regardless of which modules executed.

## Summary

- The standard output format for Holehe modules requires a dictionary with exactly nine keys: `name`, `domain`, `method`, `frequent_rate_limit`, `rateLimit`, `exists`, `emailrecovery`, `phoneNumber`, and `others`.
- Modules append these dictionaries to a shared `out` list passed by the `launch_module` function in [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py).
- The `exists` boolean indicates account presence, while `rateLimit` signals throttling issues, and `others` accommodates supplementary metadata.
- Production examples in [twitter.py](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/twitter.py) and [facebook.py](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/facebook.py) demonstrate both simple and complex implementations of the schema.
- Custom modules must use the async signature `(email, client, out)` and maintain the exact key structure for compatibility with the core aggregation engine.

## Frequently Asked Questions

### What happens if a module omits required keys from the output dictionary?

The core engine's formatting functions in [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py) expect all nine keys to be present. Omitting keys such as `exists` or `rateLimit` will raise a `KeyError` during result processing or CSV export. Always populate every field, using `None` for optional data and `False` for boolean defaults when information is unavailable.

### Can modules add custom fields outside the standard schema?

While the `others` key exists specifically for extensible metadata, adding new top-level keys outside the defined schema breaks compatibility with the core aggregation logic. Store any additional data—such as profile URLs or account creation dates—within the `others` dictionary to maintain forward compatibility with future Holehe versions.

### How does the output format handle partial or rate-limited responses?

When a module encounters rate limiting, it must set `rateLimit` to `True` and `exists` to `False`. The `frequent_rate_limit` metadata flag alerts users that the service aggressively restricts requests, allowing the CLI to implement delays or warning messages. This standardized error handling ensures consistent behavior across all 300+ supported platforms.

### Is the dictionary format consistent between CLI usage and Python API calls?

Yes. Whether invoking Holehe from the terminal, importing `launch_module` directly, or integrating the modules into larger async workflows, the standard output format remains identical. The dictionary structure serves as the universal contract between individual service modules and the core processing engine, ensuring predictable data structures regardless of the interface used.