# Holehe Result Dictionary Schema: Complete Guide to Module Output Structure

> Understand the Holehe result dictionary schema. Learn the 10 defined keys and module output structure used for display and CSV export.

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

---

**Holehe modules return a standardized dictionary with 10 defined keys that the `print_result` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) processes for display and CSV export.**

The open-source **Holehe** tool by **megadose/holehe** checks email registration status across hundreds of websites. Each module returns data in a consistent schema, enabling uniform processing of email intelligence results.

## 10 Required Keys in the Holehe Result Schema

Every module appends a dictionary to the shared output list with the following keys:

| Key | Type | Purpose |
|-----|------|---------|
| `name` | `str` | Internal module identifier (e.g., `"google"`, `"twitter"`) |
| `domain` | `str` | Target website domain (e.g., `"google.com"`) |
| `method` | `str` | HTTP method used: `"GET"` or `"POST"` |
| `frequent_rate_limit` | `bool` | Tracks repeated rate-limiting from the site |
| `rateLimit` | `bool` | Indicates current request hit rate limits |
| `error` | `bool` | True when exception or parse failure occurred |
| `exists` | `bool` | **Core finding**: True when email is registered |
| `emailrecovery` | `str \| None` | Recovered masked email if available |
| `phoneNumber` | `str \| None` | Extracted phone number if exposed |
| `others` | `dict \| None` | Additional metadata (names, dates, etc.) |

The **minimal display set** requires: `domain`, `rateLimit`, `error`, `exists`, `emailrecovery`, `phoneNumber`, and `others`. The `name`, `method`, and `frequent_rate_limit` fields support debugging and structured export.

## How Modules Build the Result Dictionary

In [`holehe/modules/mails/google.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/mails/google.py), the Google module constructs results like this:

```python

# From holehe/modules/mails/google.py

out.append({
    "name": "google",
    "domain": "google.com",
    "method": "POST",
    "frequent_rate_limit": False,
    "rateLimit": False,
    "error": False,
    "exists": True,
    "emailrecovery": None,
    "phoneNumber": None,
    "others": {"FullName": "John Doe"}  # Additional extracted data

})

```

The `out` parameter is a shared list passed by `holehe.core.maincore()` that accumulates results from all async module executions.

## Core Processing in holehe/core.py

The `print_result()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) iterates over result dictionaries to format console output. It accesses keys directly:

```python

# print_result expects consistent schema across all modules

for result in results:
    domain = result["domain"]
    exists = result["exists"]
    # ... formats colored output based on exists/True/False/None

```

This centralization enforces schema compliance—any missing required key would raise `KeyError` during display.

## Practical Examples

### Inspecting a Single Module Result

```python
import asyncio
import httpx
from holehe.modules.mails.google import google

async def inspect_schema():
    async with httpx.AsyncClient(timeout=10) as client:
        results = []
        await google("test@example.com", client, results)
        
        result = results[0]
        print(f"Module: {result['name']}")
        print(f"Domain: {result['domain']}")
        print(f"Account exists: {result['exists']}")
        print(f"Extra data: {result.get('others', {})}")

asyncio.run(inspect_schema())

```

Expected output structure:

```python
{
    "name": "google",
    "domain": "google.com", 
    "method": "POST",
    "frequent_rate_limit": False,
    "rateLimit": False,
    "error": False,
    "exists": True,
    "emailrecovery": None,
    "phoneNumber": None,
    "others": {"FullName": "John Doe"}
}

```

### Exporting Results to CSV

The CSV writer uses the same schema fields defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

```python
import csv

def export_holehe_results(data: list[dict], email: str):
    """Export Holehe results preserving the module schema."""
    fieldnames = [
        "name", "domain", "method", "frequent_rate_limit",
        "rateLimit", "error", "exists",
        "emailrecovery", "phoneNumber", "others"
    ]
    
    filename = f"holehe_{email.replace('@', '_at_')}_results.csv"
    
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(data)
    
    return filename

```

## Schema Variations Across Module Types

Different module categories use schema fields with varying emphasis:

- **Email providers** (`holehe/modules/mails/`): Heavy use of `emailrecovery` and `phoneNumber` fields
- **Social media** ([`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)): Sets `frequent_rate_limit` for aggressive rate limiting
- **Software services** ([`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py)): Populates `others` with tenant and license metadata

The [`instruments.py`](https://github.com/megadose/holehe/blob/main/instruments.py) file provides UI progress indicators but also maintains result structure definitions used by the async execution engine.

## Summary

- **10 keys** define the Holehe result dictionary schema: `name`, `domain`, `method`, `frequent_rate_limit`, `rateLimit`, `error`, `exists`, `emailrecovery`, `phoneNumber`, `others`
- **7 keys are required** for display: `domain`, `rateLimit`, `error`, `exists`, `emailrecovery`, `phoneNumber`, `others`
- **3 keys support metadata**: `name`, `method`, `frequent_rate_limit` (used for debugging and CSV export)
- The schema is enforced by `print_result()` in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) and followed by all modules in `holehe/modules/`

## Frequently Asked Questions

### What happens if a module omits a required key?

The `print_result()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) will raise a `KeyError` when attempting to access missing keys. All official modules follow the schema strictly; custom modules must implement the same structure.

### Can the `others` dictionary contain any data type?

Yes, `others` accepts any JSON-serializable data. Common contents include `FullName`, account creation dates, profile URLs, or service-specific metadata. The field is `None` when no additional data is extracted.

### How does `frequent_rate_limit` differ from `rateLimit`?

`rateLimit` indicates the **current request** triggered rate limiting (HTTP 429 or equivalent). `frequent_rate_limit` is a **persistent flag** marking sites that consistently rate-limit Holehe requests, allowing the tool to deprioritize or warn about problematic domains.