# What Information Can Holehe Extract Besides Account Existence?

> Discover what Holehe reveals beyond account existence, including recovery emails, phone numbers, names, and creation dates from public APIs and password recovery flows.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: deep-dive
- Published: 2026-08-18

---

**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`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py), the module extracts `secondaryEmail` directly from Adobe's password-recovery API response:

```python

# 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`](https://github.com/megadose/holehe/blob/main/holehe/core.py), the `print_result` function specifically checks for these keys when building output:

```python

# 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`](https://github.com/megadose/holehe/blob/main/core.py) lines 66-78. The `launch_module` function and error handling code enforce this contract:

```python

# 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

1. **Module execution** — `import_submodules` and `get_functions` discover all service modules dynamically
2. **Concurrent checking** — `trio.open_nursery()` runs all modules in parallel with an `httpx.AsyncClient`
3. **Output formatting** — `print_result` constructs human-readable lines from the collected `out` list

### Presentation Logic

The `print_result` function in [`core.py`](https://github.com/megadose/holehe/blob/main/core.py) (lines 36-46) builds colored output by concatenating any non-null extra fields:

```python

# 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

```bash

# 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

```python
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`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Orchestrates module loading, concurrent execution, and result formatting with extra field handling |
| [`holehe/modules/software/adobe.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py) | Demonstrates `emailrecovery` and `phoneNumber` extraction from Adobe's API |
| [`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py) | Populates `others` dictionary with profile metadata |
| [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) | Provides `TrioProgress` for execution monitoring |
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Supplies browser-mimicking User-Agent strings |

## Summary

- **Recovery emails**: Extracted via `emailrecovery` field when services expose secondary addresses
- **Phone numbers**: Captured in `phoneNumber` field from security/2FA information
- **Flexible metadata**: The `others` dictionary 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 `None` and 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`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/facebook.py) and [`adobe.py`](https://github.com/megadose/holehe/blob/main/adobe.py) modules represent services with more permissive information disclosure patterns.