# Holehe Module Output Structure: The Complete Developer Guide

> Understand the Holehe module output structure. Learn how to append the standardized 9-field dictionary for metadata and account discovery, essential for core engine consumption and formatted exports.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: api-reference
- Published: 2026-08-30

---

**Each Holehe module must append a standardized 9-field dictionary to the shared `out` list, containing metadata and account discovery results that the core engine consumes for formatted console output and CSV export.**

Writing effective OSINT modules for the [megadose/holehe](https://github.com/megadose/holehe) repository requires understanding exactly how the framework expects results to be structured. The [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) file processes these outputs to generate color-coded terminal reports, making strict adherence to the schema essential for interoperability.

---

## Required Output Schema for Holehe Modules

Every module function receives three parameters: `email`, `client`, and `out`. The `out` parameter is a list that collects result dictionaries from all executed modules. According to the source code in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), each dictionary must contain exactly these keys:

| Key | Type | Purpose |
|-----|------|---------|
| `name` | `str` | Module identifier (typically the function name) |
| `domain` | `str` | Target service's primary domain |
| `method` | `str` | HTTP strategy used: `"login"`, `"register"`, or similar |
| `frequent_rate_limit` | `bool` | Service reputation flag for aggressive throttling |
| `rateLimit` | `bool` | Whether this specific request hit rate limiting |
| `exists` | `bool` or `None` | Account existence: `True`=found, `False`=not found, `None`=uncertain |
| `emailrecovery` | `str` or `None` | Recovered email from password-reset flows |
| `phoneNumber` | `str` or `None` | Recovered phone number from account recovery |
| `others` | `dict` or `None` | Arbitrary additional metadata the module wishes to expose |

The core processing logic expects this schema at lines 6–49 of [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), where it iterates over `out` to determine which symbol to display: `[+]` for confirmed accounts, `[-]` for confirmed absences, `[x]` for rate limits, and `[!]` for ambiguous results.

---

## Minimal Module Skeleton

This template demonstrates the required structure with placeholder values:

```python

# holehe/modules/custom/example.py

from holehe.core import *
from holehe.localuseragent import *

async def example(email, client, out):
    name = "example"
    domain = "example.com"
    method = "login"
    frequent_rate_limit = False

    # Perform async HTTP requests with `client`

    # Determine results based on response analysis

    
    out.append({
        "name": name,
        "domain": domain,
        "method": method,
        "frequent_rate_limit": frequent_rate_limit,
        "rateLimit": False,
        "exists": True,           # Set based on response

        "emailrecovery": None,
        "phoneNumber": None,
        "others": None,
    })

```

---

## Production Implementation: GitHub Module

The `github` module in [`holehe/modules/programing/github.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/programing/github.py) illustrates the schema in action:

```python
async def github(email, client, out):
    name = "github"
    domain = "github.com"
    method = "register"
    frequent_rate_limit = False

    freq = await client.get("https://github.com/join")
    token = re.findall(
        r'<auto-check src="/signup_check/username[\s\S]*?value="([\S]+)"'
        r'[\s\S]*<auto-check src="/signup_check/email[\s\S]*?value="([\S]+)"',
        freq.text,
    )
    data = {"value": email, "authenticity_token": token[0]}
    req = await client.post("https://github.com/signup_check/email", data=data)

    if req.status_code == 422:
        exists = True
    elif req.status_code == 200:
        exists = False
    else:
        exists = None

    out.append({
        "name": name,
        "domain": domain,
        "method": method,
        "frequent_rate_limit": frequent_rate_limit,
        "rateLimit": False,
        "exists": exists,
        "emailrecovery": None,
        "phoneNumber": None,
        "others": None,
    })

```

This module uses the **register endpoint** as an existence oracle: HTTP 422 indicates the email is already registered, while 200 means it's available for new account creation.

---

## Using the `others` Field for Extended Data

The `others` key accepts any dictionary, enabling modules to surface additional account metadata beyond the core schema. While many modules set `others: None`, the field supports flexible extension:

```python
others = {
    "fullName": "Jane Smith",
    "accountCreated": "2019-03-15",
    "profileUrl": "https://example.com/user/janesmith"
}

```

When populated, this data appears in JSON exports and can be processed by downstream tooling that consumes Holehe's structured output.

---

## Core Engine Processing

The [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) file implements the consumer side of this contract. Key processing behaviors include:

- **Symbol selection**: Based on `exists` and `rateLimit` values
- **Color coding**: Green for found, red for not found, yellow for rate limits, white for uncertain
- **CSV serialization**: Flattening the `others` dictionary when present
- **Rate limit aggregation**: Tracking `frequent_rate_limit` for user warnings

Modules that deviate from the schema will cause `KeyError` exceptions during result formatting, terminating the scan prematurely.

---

## Summary

- **Nine required keys** form the standardized Holehe module output structure
- **Append to `out`**—never return values directly from module functions
- **Use `exists=None`** when response ambiguity prevents definitive determination
- **Leverage `others`** for extended metadata without breaking core compatibility
- **Reference [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)** for validation of your module's output handling

---

## Frequently Asked Questions

### What happens if I omit a required key from the output dictionary?

The core engine will raise a `KeyError` when attempting to format results, causing the entire scan to crash. Always include all nine keys, using `None` or `False` as appropriate for empty values.

### Can I add custom keys beyond the nine specified fields?

No—the core processing logic expects exactly this schema. Use the `others` dictionary to encapsulate any additional data your module discovers.

### How do I indicate that a service is blocking requests?

Set `rateLimit=True` when the response indicates CAPTCHA challenges, IP blocking, or explicit rate limiting. Set `frequent_rate_limit=True` in the module metadata if the service is known for aggressive throttling behavior.

### Where are real-world module examples located?

Study the implementations in [`holehe/modules/programing/github.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/programing/github.py) and [`holehe/modules/productivity/evernote.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/productivity/evernote.py) for production patterns. The [`holehe/modules/__init__.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/__init__.py) file handles dynamic module discovery for the framework.