# Can Holehe Recover Partially Obfuscated Email Addresses? How the OSINT Tool Captures Masked Recovery Data

> Discover if Holehe can recover partially obfuscated email addresses by analyzing password recovery data and extracting masked formats like ex****e@gmail.com.

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

---

**Yes — Holehe can recover partially obfuscated email addresses by querying password‑recovery endpoints and extracting the `emailrecovery` field that services return, which often contains masked formats like `ex****e@gmail.com`.**

Holehe is an open‑source OSINT tool developed by megadose that checks whether an email address is registered across hundreds of online services. A lesser‑known but powerful feature is its ability to capture **partially obfuscated recovery emails** that websites expose during forgotten‑password flows. This article explains exactly how Holehe extracts this data, where the functionality lives in the codebase, and how to use it from both the command line and Python.

---

## How Holehe Captures Obfuscated Recovery Emails

The recovery process relies on Holehe's modular architecture. When you run a query, the tool spawns asynchronous tasks for every installed module, each one mimicking a legitimate password‑recovery request to a target service.

### Module Discovery and Loading

In [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), the `import_submodules` function dynamically loads every Python file under `holehe/modules/**`:

```python

# holehe/core.py (lines 37-47)

def import_submodules(package, recursive=True):
    """ Import all submodules of a module, recursively """
    results = {}
    for loader, name, is_pkg in pkgutil.walk_packages(package.__path__):
        full_name = package.__name__ + '.' + name
        results[full_name] = importlib.import_module(full_name)
        if recursive and is_pkg:
            results.update(import_submodules(results[full_name]))
    return results

```

Each loaded module exposes an async function that receives three arguments: the target email, an `httpx.AsyncClient` instance, and a shared `out` list that aggregates results across all modules.

### Sending Recovery Requests

A typical module implements the password‑recovery flow specific to its target service. The Adobe module in [`holehe/modules/software/adobe.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py) demonstrates this pattern:

```python

# holehe/modules/software/adobe.py (lines 22-28)

csrfToken = await get_csrf_token(client)
data = {
    "username": email,
    "_csrf": csrfToken,
    "fromPage": "unity.sso"
}
req = await client.post(
    "https://accounts.adobe.com/signin/sessions",
    data=data,
    headers=headers
)

```

The request payload mirrors what a genuine browser would send during an account recovery attempt.

### Parsing Masked Email Responses

After the POST completes, the module inspects the JSON response for recovery information. If the service exposes a secondary email — even in obfuscated form — the module captures it:

```python

# holehe/modules/software/adobe.py (lines 55-61)

json_response = json.loads(req.text)
if "secondaryEmail" in json_response:
    secondary_email = json_response["secondaryEmail"]
    # Adobe may return: "ex****e@example.com"

    out.append({
        "name": "adobe",
        "domain": "adobe.com",
        "method": "password recovery",
        "frequent_rate_limit": False,
        "rateLimit": False,
        "exists": True,
        "emailrecovery": secondary_email,  # <-- captures obfuscated address

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

```

The `emailrecovery` field is deliberately designed to hold whatever string the service returns, whether fully visible or partially masked.

### Result Aggregation and Display

The `print_result` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) iterates through the `out` list and surfaces any non‑null `emailrecovery` values:

```python

# holehe/core.py (lines 135-141)

for result in out:
    if result["exists"]:
        print(f"[+] {result['domain']}", end="")
        if result["emailrecovery"]:
            print(f" {result['emailrecovery']}", end="")
        print()

```

This is where you see output like `[+] adobe.com ex****e@example.com` — the masked address passed through unchanged from the remote service.

---

## Using Holehe to Recover Partially Obfuscated Emails

### Command Line Interface

The simplest way to check for exposed recovery addresses is via the CLI:

```bash
holehe alice@example.com

```

Sample output showing both masked and full recovery emails:

```

[+] adobe.com ex****e@example.com
[+] twitter.com alice@example.com
[-] instagram.com
[+] github.com al****ce@example.com
[-] netflix.com

```

The `ex****e@example.com` entry demonstrates Adobe's masking policy. The degree of obfuscation varies by platform — some services return complete addresses, others aggressively mask username portions or domains.

### Programmatic Usage in Python

For integration into larger workflows, import Holehe's machinery directly:

```python
import trio
import httpx
from holehe.modules.social_media.twitter import twitter
from holehe.core import launch_module

async def main():
    email = "alice@example.com"
    out = []
    client = httpx.AsyncClient(timeout=10)

    # Execute a single module asynchronously

    await launch_module(twitter, email, client, out)

    # Filter and display recovery emails (possibly obfuscated)

    for result in out:
        if result.get("emailrecovery"):
            print(f"{result['domain']}: {result['emailrecovery']}")

    await client.aclose()

trio.run(main)

```

Running this against Twitter might yield:

```

twitter.com: al****e@example.com

```

The `launch_module` wrapper handles exception catching and timeout management, ensuring one failing module doesn't crash the entire scan.

---

## Key Files and Implementation Details

| File | Purpose | Lines of Interest |
|------|---------|-------------------|
| [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) | Orchestrates module loading, async execution, and result formatting. | 37-47 (`import_submodules`), 135-141 (`print_result`) |
| [`holehe/modules/software/adobe.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py) | Exemplary module showing recovery request construction and masked email extraction. | 22-28 (request), 55-61 (response parsing) |
| [`README.md`](https://github.com/megadose/holehe/blob/main/README.md) | Documents the `emailrecovery` output field, explicitly noting partial obfuscation support. | Module Output section |

The README states unambiguously: *"emailrecovery : Sometimes partially obfuscated recovery emails are returned."* This confirms the intentional design choice to surface whatever masking the target service applies.

---

## Factors Affecting Recovery Success

- **Service‑specific masking policies**: Each platform controls its own obfuscation logic. Adobe tends to mask the middle of the username; Twitter historically showed more complete addresses.
- **Account configuration**: Recovery emails only appear if the user has actually configured a secondary address.
- **Rate limiting and bot detection**: Aggressive scanning may trigger protection mechanisms that alter or block responses.
- **Regional variations**: Some services return different response formats based on geolocation or IP reputation.

Holehe has no capability to *reverse* or *de‑obfuscate* masked addresses — it faithfully reports the string received from the remote endpoint.

---

## Summary

- **Holehe captures partially obfuscated email addresses** through its `emailrecovery` field, populated from password‑recovery endpoint responses.
- **Implementation spans [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)** for orchestration and individual modules like [`holehe/modules/software/adobe.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/adobe.py) for service‑specific extraction logic.
- **Output format preserves whatever masking the target service applies** — there is no de‑obfuscation performed.
- **Both CLI and Python API expose this data**, making it accessible for manual investigation and automated pipelines.
- **Success depends on the target service's masking policy**, not Holehe's capabilities.

---

## Frequently Asked Questions

### How accurate is the emailrecovery data from Holehe?

The `emailrecovery` value is exactly what the target service returns — no transformation occurs. Accuracy depends entirely on the remote platform's response. If a service masks `alice@example.com` as `al****e@example.com`, Holehe reports the masked version without modification. Always verify critical findings through independent channels.

### Can Holehe de‑obfuscate or unmask email addresses?

No. Holehe has no de‑obfuscation capability. The tool captures and forwards whatever string the password‑recovery endpoint provides. Reconstructing the full address from a masked version like `ex****e@gmail.com` is not mathematically possible without additional data sources.

### Why do some services return full emails while others mask aggressively?

Masking policy is determined by each platform's security engineering team. Factors include regulatory requirements (GDPR, CCPA), threat model assessments, and historical abuse patterns. Holehe adapts to whatever policy is in place — it cannot influence or bypass server‑side masking decisions.

### Does using Holehe violate terms of service or laws?

Holehe performs unauthenticated queries against publicly accessible password‑recovery endpoints. Legal and ethical permissibility depends on your jurisdiction, the target service's terms of service, and your purpose. The tool is designed for legitimate security research and personal account recovery; misuse for harassment, unauthorized access, or data harvesting may violate computer fraud statutes or platform policies.