What Causes Error Results in the Holehe Module and How to Debug Them
Holehe reports error results when the asynchronous function checking a specific service raises an exception, which launch_module in holehe/core.py catches and converts to "error": True in the output.
Holehe is an open-source OSINT tool for checking if an email address is registered on various websites. Understanding why some services return errors—and how to troubleshoot them—is essential for accurate investigations and maintaining reliable results. This guide explains the root causes of error results in Holehe and provides actionable debugging techniques based on the megadose/holehe source code.
How Holehe Handles Errors Internally
The launch_module Exception Catcher
Every service check in Holehe flows through the launch_module helper function located in holehe/core.py. This function wraps each module execution in a try/except block that silently catches all exceptions and converts them to error results.
async def launch_module(module, email, client, out):
try:
await module(email, client, out)
except Exception:
name = str(module).split('<function ')[1].split(' ')[0]
out.append({
"name": name,
"domain": data[name],
"rateLimit": False,
"error": True, # ← error flag set here
"exists": False,
"emailrecovery": None,
"phoneNumber": None,
"others": None
})
When any exception bubbles up from a module, the code extracts the function name and appends a standardized dictionary with "error": True. This design ensures that one failing module doesn't crash the entire scan.
Visual Error Indicators in Output
The print_result function (also in holehe/core.py) formats error entries with a red [!] prefix for terminal visibility:
elif "error" in results.keys() and results["error"] and args.onlyused == False:
websiteprint = print_color("[!] " + results["domain"] + toprint, "red", args)
Seeing [!] next to a domain means that module encountered an unhandled exception during execution.
Common Root Causes of Error Results
Network-Related Failures
- DNS resolution failures when a service domain is unreachable
- Connection refused or reset errors
- HTTP 429 responses (rate limiting) that modules don't explicitly handle
- SSL/TLS certificate problems on older Python versions
Unexpected Response Formats
Website changes frequently break Holehe modules. Common parsing failures include:
- KeyError when expected JSON keys are renamed or removed
- IndexError when HTML structure changes and selectors return empty lists
- AttributeError when attempting to access properties on NoneType objects
Timeout Exceedances
Holehe uses a default 10-second timeout (configurable via --timeout). Slow services or poor network conditions can trigger premature timeouts that register as errors.
Anti-Automation Blocks
Some services implement:
- CAPTCHA challenges that return unexpected page content
- JavaScript-rendered responses that static requests cannot parse
- Bot detection redirects to verification flows
Debugging Error Results in Holehe: Step-by-Step Methods
Enable Internal Debugging
Set DEBUG = True in holehe/core.py (approximately line 31) to unlock verbose logging throughout the codebase:
# In holehe/core.py
DEBUG = True
This activates print statements that reveal request URLs, HTTP status codes, response headers, and intermediate parsing results. The output includes lines like:
[DEBUG] GET https://www.facebook.com/login/identify/?email=example%40example.com
[DEBUG] Response status: 200
[DEBUG] Parsing JSON …
Run a Single Module in Isolation
Isolate the failing module to see the full exception traceback without orchestration overhead:
import asyncio
import httpx
from holehe.modules.social_media.facebook import facebook
async def test():
async with httpx.AsyncClient(timeout=30) as client:
results = []
await facebook('test@example.com', client, results)
print(results)
asyncio.run(test())
This approach surfaces the exact line number and exception type causing the failure.
Increase the Request Timeout
Use --timeout 30 or higher when launching Holehe to eliminate false-positive errors from slow services:
holehe --timeout 30 example@example.com
Some international services require 20-30 seconds for complete response cycles.
Inspect Raw HTTP Responses
Modify a module temporarily to print response data before parsing:
async def facebook(email, client, out):
response = await client.get(
f"https://facebook.com/login/identify/?email={email}"
)
print(f"Status: {response.status_code}")
print(f"Body preview: {response.text[:500]}")
# ... existing parsing logic
This reveals whether the service returned an error page, redirect, or changed API format.
Extract the errorMessage Field
Some modules populate results["others"]["errorMessage"] with additional context. Check if the verbose output contains more specific information beyond the generic error flag.
Examine the Module Source Code
Open the specific module file under holehe/modules/ that corresponds to the failing domain. For example:
holehe/modules/social_media/facebook.pyholehe/modules/software/adobe.pyholehe/modules/shopping/amazon.py
Most modules follow a consistent pattern: HTTP request → response validation → data extraction → result appending. Look for brittle selectors or hardcoded API endpoints that may have changed.
Update to the Latest Version
Website changes are constantly patched. Update Holehe via:
holehe --check-update
# or
pip install -U holehe
The megadose/holehe repository receives frequent updates to fix modules broken by third-party API changes.
Practical Code Examples
Basic Execution with Error Observation
holehe example@example.com
Sample output showing error results:
[+] twitter.com
[-] facebook.com
[!] instagram.com Error message: Request timeout
The [!] prefix indicates instagram raised an exception during processing.
Debugging with Verbose Python Execution
PYTHONVERBOSE=1 holehe example@example.com 2>&1 | grep -i error
This surfaces low-level Python import and execution details when environment-level issues are suspected.
Programmatic Error Handling
import asyncio
from holehe.core import launch_module
from holehe.modules.shopping.amazon import amazon
import httpx
async def safe_check():
async with httpx.AsyncClient() as client:
results = []
try:
await launch_module(amazon, "test@example.com", client, results)
except Exception as e:
print(f"Uncaught exception: {type(e).__name__}: {e}")
for r in results:
if r.get("error"):
print(f"Service {r['name']} failed: {r}")
asyncio.run(safe_check())
Key Source Files for Error Investigation
| File | Purpose | Critical Components |
|---|---|---|
holehe/core.py |
Module orchestration and error handling | launch_module(), print_result(), DEBUG flag |
holehe/modules/*/*.py |
Individual service checkers | Module-specific request logic and parsing |
holehe/localuseragent.py |
User-Agent rotation | Missing or outdated headers can cause blocks |
holehe/instruments.py |
Progress visualization | TrioProgress for monitoring execution flow |
Summary
- Error results originate from unhandled exceptions in individual service modules, caught by
launch_moduleinholehe/core.pyand converted to"error": Trueflags - Network issues, parsing failures, timeouts, and anti-bot measures are the primary categories of root causes
- Debug effectively by enabling
DEBUG = True, running modules in isolation, increasing timeouts, and inspecting raw responses - Maintain accuracy by regularly updating Holehe and inspecting module source code when services change their implementations
Frequently Asked Questions
How can I tell if an error is temporary or permanent?
Temporary errors typically involve network timeouts or HTTP 5xx status codes. Permanent errors stem from changed APIs or removed endpoints. Run the module in isolation multiple times—if it fails consistently with the same exception type and message, the module likely needs updating. Check the megadose/holehe repository issues for confirmed breakages.
Does Holehe retry failed requests automatically?
No. The launch_module function catches exceptions on the first failure and immediately returns the error result. There is no built-in retry logic. For transient network issues, implement your own retry wrapper or increase the --timeout value to reduce timeout-related errors.
Can I suppress error results from the output?
Yes. Pass --only-used or -o when running Holehe. The print_result logic checks args.onlyused == False before displaying error entries, so this flag filters out all services that don't return a definitive "exists" or "does not exist" status—including error results.
Why does a service show error even though the website works in my browser?
Browsers execute JavaScript, handle redirects automatically, and maintain session cookies. Holehe modules use static HTTP requests without JavaScript rendering. If a service requires JavaScript or sophisticated session management, the module may fail with parsing errors or unexpected redirects that don't occur in interactive browsing.
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 →