Holehe Result Dictionary Schema: Complete Guide to Module Output Structure
Holehe modules return a standardized dictionary with 10 defined keys that the print_result function in 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, the Google module constructs results like this:
# 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 iterates over result dictionaries to format console output. It accesses keys directly:
# 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
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:
{
"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:
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 ofemailrecoveryandphoneNumberfields - Social media (
holehe/modules/social_media/twitter.py): Setsfrequent_rate_limitfor aggressive rate limiting - Software services (
holehe/modules/software/office365.py): Populatesotherswith tenant and license metadata
The 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()inholehe/core.pyand followed by all modules inholehe/modules/
Frequently Asked Questions
What happens if a module omits a required key?
The print_result() function in 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →