# Holehe JSON Output Format: Standardized Schema and Field Reference

> Understand the Holehe JSON output format with a standardized schema and field reference. Learn about exists, rateLimit, emailrecovery, and others in this guide.

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

---

**Holehe returns email-check results as a list of flat Python dictionaries that serialize directly to JSON, with each entry containing standardized fields like `exists`, `rateLimit`, `emailrecovery`, and `others`.**

Holehe is an open-source OSINT tool by @megadose that checks whether an email address is registered across hundreds of websites. Understanding the **Holehe JSON output format** is essential for building automated workflows, because the tool's programmatic value lies in this consistent, machine-readable schema. The format is defined implicitly in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) and implemented by every module in `holehe/modules/`.

## Core Structure: A List of Uniform Dictionaries

Holehe aggregates results into a single Python list variable named `out`. Each element is a dictionary representing one site check. Because the structure uses only built-in types—strings, booleans, `None`, and nested dicts—it requires no custom encoders.

```python
from holehe.core import launch_module

# Inside the execution loop, each module appends to `out`:

out = []  # Collects all results

await launch_module(site, email, client, out)

# `out` is now JSON-serializable

```

The list structure enables parallel processing and simple downstream parsing with standard JSON libraries.

## Standard Fields in Every Holehe JSON Entry

Every dictionary follows the same schema, whether produced by [`twitter.py`](https://github.com/megadose/holehe/blob/main/twitter.py), [`blablacar.py`](https://github.com/megadose/holehe/blob/main/blablacar.py), or any other module. Fields are populated according to the site's response and the module's capabilities.

| Field | Type | Purpose |
|-------|------|---------|
| `name` | `str` | Internal module identifier (e.g., `"blablacar"`). |
| `domain` | `str` | Public domain queried (e.g., `"blablacar.com"`). |
| `method` | `str` \| absent | HTTP method used: `"register"`, `"login"`, etc. |
| `frequent_rate_limit` | `bool` \| absent | Whether the service commonly returns rate limits. |
| `rateLimit` | `bool` | `True` if the request was blocked temporarily. |
| `error` | `bool` | `True` if the module raised an unexpected exception. |
| `exists` | `bool` | `True` if the email is registered on this service. |
| `emailrecovery` | `str` \| `None` | Password-recovery hint (masked email) if exposed. |
| `phoneNumber` | `str` \| `None` | Recovered phone number if exposed. |
| `others` | `dict` \| `None` | Additional metadata (name, dates, raw responses). |

The `name` and `domain` fields are guaranteed. Optional fields appear only when modules explicitly set them.

## How Fields Are Populated: Source Code Analysis

### Automatic Fields from Core Logic

In [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), the `launch_module` function provides fallback handling when a module crashes. This fallback constructs a minimal valid entry:

```python

# holehe/core.py lines 71-73 (simplified)

name = str(module).split('<function ')[1].split(' ')[0]
data[name] = {"exists": False, ...}  # domain derived similarly

out.append({"name": name, "domain": data[name], ...})

```

The fallback also sets `error: True` when an exception occurs, ensuring the output remains schema-compliant even during failures.

### Module-Generated Fields

Individual modules populate the remaining fields based on HTTP responses. Consider [`blablacar.py`](https://github.com/megadose/holehe/blob/main/blablacar.py):

```python

# holehe/modules/transport/blablacar.py lines 5-9

def blablacar(email, client, out):
    # Module metadata

    method = "register"
    frequent_rate_limit = True
    # ... request logic ...

```

On success (lines 68-74), it returns:

```python
{
    "exists": True,           # Email found on service

    "rateLimit": False,       # No throttling occurred

    "emailrecovery": None,    # No recovery hint extracted

    "phoneNumber": None,
    "others": None
}

```

The `others` field captures unstructured data. For example, if a module extracts a user's full name or account creation date, it places these in `others` rather than polluting the top-level schema.

## Working with Holehe JSON Output

### Command-Line JSON Export

Holehe's table output is human-readable but not machine-friendly. Capture raw JSON using Python's eval-to-JSON pattern:

```bash

# Basic CLI usage (colored table)

holehe test@example.com

# Extract valid JSON

holehe test@example.com --no-color --no-clear | \
    python -c "import sys, json; print(json.dumps(eval(sys.stdin.read())))"

```

### Library Usage for Programmatic Access

For production automation, import Holehe directly:

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

async def check_email(email: str) -> str:
    """Return Holehe results as a JSON string."""
    modules = import_submodules("holehe.modules")
    sites = get_functions(modules)
    
    out = []
    async with httpx.AsyncClient() as client:
        for site in sites:
            await launch_module(site, email, client, out)
    
    return json.dumps(out, indent=2)

# Execute

result = asyncio.run(check_email("target@example.com"))
print(result)

```

Sample output:

```json
[
  {
    "name": "blablacar",
    "domain": "blablacar.com",
    "method": "register",
    "frequent_rate_limit": true,
    "rateLimit": false,
    "error": false,
    "exists": true,
    "emailrecovery": null,
    "phoneNumber": null,
    "others": null
  }
]

```

## Field-by-Field Reference for Automation

### `exists` vs. `rateLimit` vs. `error`

These three booleans encode distinct failure modes:

- **`exists: True`** — Confirmed registration. The email has an account.
- **`rateLimit: True`** — Cannot determine; the service blocked the request. Retry later.
- **`error: True`** — Module crashed. The result is unreliable; check logs.

A result with `exists: False` and `rateLimit: True` is **inconclusive**, not negative.

### `emailrecovery` and `phoneNumber` Pattern Matching

When services expose password-recovery hints, modules attempt extraction:

```python

# Typical extraction pattern in modules

"emailrecovery": response.text.split('maskedEmail":"')[1].split('"')[0],

```

These fields often contain partially redacted values like `t***@example.com`. Parse defensively—services change their masking formats without warning.

### Extending with `others`

The `others` field preserves forward compatibility. When Holehe adds new extractors, they place data here rather than breaking existing parsers. Structure varies by module:

```json
"others": {
    "full_name": "John Doe",
    "created_at": "2019-03-15",
    "raw_error": "Invalid captcha"  # Even errors may appear here

}

```

## Key Files Defining the Output Format

| Path | Responsibility |
|------|--------------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Orchestration, fallback entry construction, error handling. Contains `launch_module` and the schema fallback. |
| `holehe/modules/**/*.py` | Site-specific logic. Every module must return a dictionary matching the core schema. |
| [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) | Progress instrumentation (does not affect output format). |

## Summary

- Holehe produces a **list of flat dictionaries** that serialize directly to JSON without custom encoders.
- **Ten standardized fields** cover identification (`name`, `domain`), status (`exists`, `rateLimit`, `error`), and extracted intelligence (`emailrecovery`, `phoneNumber`, `others`).
- The **core fallback in `launch_module`** ensures schema compliance even when modules crash.
- **`others` provides an extension point** for unstructured data without breaking backward compatibility.
- For automation, import `launch_module` directly rather than parsing CLI output.

## Frequently Asked Questions

### How do I know if an email is definitely not registered?

You cannot be certain when `rateLimit: True`. Only `exists: False` with `rateLimit: False` indicates absence. Rate-limited responses require retry.

### Why is `emailrecovery` often null?

Most services mask recovery hints or require additional authentication steps. Modules populate this field only when the unauthenticated response exposes recoverable data.

### Can I add custom fields to the output?

Yes, through the `others` dictionary in your own module. Do not add top-level fields—this breaks compatibility with standard Holehe parsers.

### What version of Holehe uses this exact schema?

The schema described reflects the current `master` branch as implemented in `megadose/holehe`. Specific field availability (`method`, `frequent_rate_limit`) depends on whether individual modules choose to populate them.