How Holehe Handles Sites That Return Obfuscated Recovery Information
Holehe extracts masked email addresses and phone numbers exactly as displayed by target sites, preserving obfuscated strings like "j*@gmail.com" without attempting de-obfuscation, and returns None when no recovery data is exposed.**
Holehe is an open-source OSINT (Open Source Intelligence) tool maintained by megadose that checks where an email address is registered across hundreds of web services. When investigating how Holehe handles sites that return obfuscated recovery information, the tool's module-based architecture reveals a design philosophy of transparency: it captures masked data verbatim rather than attempting speculative reconstruction.
The Standard Module Workflow for Recovery Data
Every Holehe module follows a consistent five-step pattern to handle password recovery pages. The workflow begins in holehe/localuseragent.py, which supplies realistic User-Agent strings to avoid detection. The module then performs an initial GET request to the target site's login or recovery endpoint, parsing the HTML response with BeautifulSoup to inspect for recovery data elements.
When a service deliberately hides the full address—displaying only obfuscated placeholders like "j***@gmail.com" or masked phone numbers—the module captures that exact string. If no recovery field is present, the module records None. Finally, each module appends a standardized result dictionary to the shared out list, containing keys for emailrecovery, phoneNumber, and others.
Extracting Obfuscated Data in Practice
Social Media Recovery Parsing (Odnoklassniki)
The Odnoklassniki module at holehe/modules/social_media/odnoklassniki.py demonstrates how Holehe handles partially masked credentials. The code inspects <button> elements with specific data-l attributes—specifically data-l="t,email" and data-l="t,phone"—to extract recovery information.
When these elements contain text (e.g., a masked email address), the module stores the raw string directly in the result dictionary. If the attributes are absent or empty, the fields remain None. This approach preserves whatever obfuscation the service applies, ensuring the tool reports exactly what an attacker or investigator would see in a browser.
JSON-Based Recovery Checks (Adobe)
In holehe/modules/software/adobe.py, the module attempts to locate secondary email addresses within JSON responses returned by Adobe's endpoints. Around lines 59-66, the code checks for specific keys in the response body. When the service does not expose a secondary email—either because it is hidden or not configured—the module explicitly sets the emailrecovery value to None rather than fabricating data.
No-Exposure Services (Blablacar)
Not all services reveal recovery information during the lookup phase. The Blablacar module at holehe/modules/transport/blablacar.py represents services that provide no recovery data at all. In such cases, the module directly constructs a result dictionary with "emailrecovery": None, maintaining consistent output structure while accurately reflecting the absence of visible data.
Core Orchestration and Result Aggregation
The central logic driving this behavior resides in holehe/core.py. This orchestrator iterates over selected modules, passes the shared out list for population, and returns the accumulated results. Crucially, the core makes no assumptions about the format of recovery data—it does not validate whether strings are obfuscated, de-obfuscated, or null. This architectural decision keeps the tool simple and avoids speculative processing, ensuring that whatever the module extracts (masked or otherwise) is returned verbatim to the user.
Practical Implementation Example
To observe how Holehe captures obfuscated recovery data, execute the following:
from holehe import core
import asyncio
async def run():
email = "test@example.com"
results = await core.check(email, modules=["odnoklassniki", "adobe"])
for r in results:
print(r["name"], r["emailrecovery"])
asyncio.run(run())
If Odnoklassniki returns a masked address like j***@mail.ru while Adobe exposes no secondary email, the output will be:
odnoklassniki j***@mail.ru
adobe None
Summary
- Holehe modules extract masked recovery strings exactly as presented by target sites without attempting de-obfuscation.
- The tool returns
NoneforemailrecoveryandphoneNumberwhen services hide this data entirely or do not expose it during the lookup phase. - The
core.pyorchestrator aggregates results from all modules without validating or transforming the recovery data format. - Implementation details vary by service: Odnoklassniki parses HTML button attributes, Adobe inspects JSON responses, and transport modules like Blablacar default to
None.
Frequently Asked Questions
Does Holehe attempt to de-obfuscate masked email addresses?
No. According to the source code in holehe/modules/social_media/odnoklassniki.py, Holehe captures the masked string (e.g., "j***@gmail.com") exactly as displayed by the service and stores it in the emailrecovery field. The tool does not implement logic to reverse-engineer the original address from partial masks.
What happens when a site doesn't expose any recovery information?
When services like Blablacar do not display recovery data on their public-facing endpoints, the respective module explicitly sets "emailrecovery": None before appending the result to the output list. This ensures a consistent data structure across all checked services, clearly indicating when information is unavailable rather than missing.
How does Holehe ensure it receives the same obfuscated data as a regular user?
Each module utilizes realistic User-Agent strings defined in holehe/localuseragent.py and standard HTTP headers when requesting password recovery pages. This ensures the target site responds with the same HTML or JSON content—including obfuscated recovery fields—that would be visible to a legitimate user accessing the page through a standard browser.
Can Holehe differentiate between partially masked and fully visible recovery data?
The core logic in holehe/core.py treats all recovery data opaquely. The orchestrator simply aggregates whatever string the module supplies—whether fully visible, partially masked, or None—without parsing the content to categorize the level of obfuscation. This design keeps the tool agnostic to the specific masking strategies employed by different web services.
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 →