What Information Can Holehe Extract Besides Account Existence?
Holehe can extract recovery email addresses, phone numbers, and free-form metadata including full names and account creation dates when services expose them through their password-recovery flows or public APIs.
Holehe is an open-source email reconnaissance tool by megadose/holehe that checks whether an email address is registered across thousands of online services. While its primary output is a Boolean exists flag indicating account presence, the tool's modular architecture allows each service module to harvest additional data when available.
The Three Extra Data Fields Holehe Captures
Holehe standardizes supplementary information into three optional properties returned by every module. These fields populate when a service's response leaks account metadata beyond simple existence confirmation.
emailrecovery: Secondary Email Addresses
The emailrecovery field captures alternate email addresses linked to an account for password recovery purposes.
In holehe/modules/software/adobe.py, the module extracts secondaryEmail directly from Adobe's password-recovery API response:
# From adobe.py lines 59-60
response['secondaryEmail'] # → emailrecovery
response['securityPhoneNumber'] # → phoneNumber
This represents one of the most common leakage patterns: services that pre-fill recovery information when an email is recognized.
phoneNumber: Linked Phone Numbers
The phoneNumber field retrieves telephone numbers associated with accounts, typically used for two-factor authentication or SMS recovery.
As shown in the Adobe module implementation, securityPhoneNumber propagates directly to this standardized field. Other modules implement similar extraction patterns for services that expose partial or complete phone digits during verification flows.
others: Free-Form Metadata Dictionary
The others dictionary serves as a flexible container for any additional account information a module can harvest. Common entries include:
- FullName — the account holder's display name
- Date, time of the creation — account registration timestamp
In holehe/core.py, the print_result function specifically checks for these keys when building output:
# From core.py lines 41-45
if i["others"] and "FullName" in i["others"]:
toprint += " / FullName: "+str(i["others"]["FullName"])
if i["others"] and "Date, time of the creation" in i["others"]:
toprint += " / Date, time of the creation: "+str(i["others"]["Date, time of the creation"])
How Holehe's Architecture Enables Metadata Extraction
Module Return Contract
Every async module in holehe follows a strict return dictionary structure defined in core.py lines 66-78. The launch_module function and error handling code enforce this contract:
# Standard module return structure
{
"name": "service_name",
"domain": "example.com",
"rateLimit": False,
"exists": True,
"emailrecovery": "backup@email.com", # or None
"phoneNumber": "+1234567890", # or None
"others": {"FullName": "Alice Smith"} # or None
}
Result Aggregation Pipeline
- Module execution —
import_submodulesandget_functionsdiscover all service modules dynamically - Concurrent checking —
trio.open_nursery()runs all modules in parallel with anhttpx.AsyncClient - Output formatting —
print_resultconstructs human-readable lines from the collectedoutlist
Presentation Logic
The print_result function in core.py (lines 36-46) builds colored output by concatenating any non-null extra fields:
# Simplified representation of print_result logic
toprint = f"[+] {domain} {email}"
if emailrecovery:
toprint += f" / {emailrecovery}"
if phoneNumber:
toprint += f" / {phoneNumber}"
# plus others dictionary inspection...
Practical Usage Examples
Command-Line Interface
# Basic check - shows all extractable information
holehe alice@example.com
Typical output format:
[+] adobe.com alice@example.com / recovery@backup.com / +15551234567
[+] facebook.com alice@example.com / FullName: Alice Smith / Date, time of the creation: 2015-03-12
[-] twitter.com
[x] github.com # rate-limited
Programmatic API Access
import asyncio
import httpx
import trio
from holehe.core import import_submodules, get_functions, print_result
async def extract_metadata(email):
"""Programmatically access all fields holehe can extract."""
modules = import_submodules("holehe.modules")
websites = get_functions(modules)
client = httpx.AsyncClient(timeout=10)
out = []
async with trio.open_nursery() as nursery:
for site in websites:
nursery.start_soon(site, email, client, out)
await client.aclose()
# Raw access to extracted data before formatting
for result in out:
if result["exists"]:
print(f"Service: {result['domain']}")
print(f" Recovery email: {result.get('emailrecovery')}")
print(f" Phone: {result.get('phoneNumber')}")
print(f" Other metadata: {result.get('others')}")
# Or use built-in formatter
print_result(out, email=email, websites=websites)
asyncio.run(extract_metadata("target@example.com"))
Key Implementation Files
| File | Purpose |
|---|---|
holehe/core.py |
Orchestrates module loading, concurrent execution, and result formatting with extra field handling |
holehe/modules/software/adobe.py |
Demonstrates emailrecovery and phoneNumber extraction from Adobe's API |
holehe/modules/social_media/facebook.py |
Populates others dictionary with profile metadata |
holehe/instruments.py |
Provides TrioProgress for execution monitoring |
holehe/localuseragent.py |
Supplies browser-mimicking User-Agent strings |
Summary
- Recovery emails: Extracted via
emailrecoveryfield when services expose secondary addresses - Phone numbers: Captured in
phoneNumberfield from security/2FA information - Flexible metadata: The
othersdictionary contains name, creation date, and service-specific fields - Standardized architecture: Every module returns the same structure, enabling consistent extraction across thousands of services
- Conditional disclosure: All extra fields remain
Noneand hidden when services don't leak them
Frequently Asked Questions
Does holehe always extract phone numbers and recovery emails?
No. These fields only populate when the target service exposes them through password-recovery flows or API responses. Many services return existence confirmation without revealing additional metadata. The adobe.py module demonstrates successful extraction, but most modules return None for these fields.
Can I access the raw metadata programmatically without the CLI formatter?
Yes. The out list returned by module execution contains complete dictionaries with all extracted fields. Bypass print_result and iterate through results directly to access emailrecovery, phoneNumber, and others values in your own code.
What determines which services leak extra information?
Service-specific implementation details vary widely. Some platforms pre-fill recovery forms with masked contact information, while others reveal nothing until full authentication. The facebook.py and adobe.py modules represent services with more permissive information disclosure patterns.
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 →