Holehe Detection Methods: How Modules Verify Email Registration Across Services
Holehe modules use six standardized detection methods—existence checks, password-recovery probing, phone-number extraction, metadata harvesting, rate-limit monitoring, and error handling—to determine if an email address is registered on a target service.
The open-source OSINT tool Holehe (megadose/holehe) employs a modular architecture to probe hundreds of services for email address registration. Each module implements holehe detection methods through a standardized result schema defined in the core engine, enabling consistent aggregation of account discovery data across disparate platforms.
The Standardized Result Schema in holehe/core.py
According to the source code in holehe/core.py (lines 35‑48 and 67‑78), every module returns a dictionary with specific fields representing different detection outcomes. This schema ensures that whether a module queries Twitter's forgot-password endpoint or GitHub's user API, the output follows a predictable structure that the central orchestrator can aggregate and display.
# Core result handling (holehe/core.py)
out.append({
"name": "twitter",
"domain": "twitter.com",
"rateLimit": False,
"error": False,
"exists": True,
"emailrecovery": "Password reset link sent",
"phoneNumber": None,
"others": {"FullName": "John Doe"},
})
Six Primary Detection Methods Used by Holehe Modules
Each field in the result dictionary corresponds to a specific detection technique implemented by the modules.
Direct Existence Verification
The exists field represents the fundamental direct existence check. Modules send HTTP requests—often to login forms or account endpoints—and parse responses for positive confirmation that the email associates with an active account. In holehe/modules/programing/github.py, the module queries the unauthenticated users API, interpreting a 200 status code as confirmation (setting exists to True) and 404 as non-existence.
Password Recovery Probing
The emailrecovery field captures results from password-recovery probing. Modules trigger "forgot password" workflows and scrape response messages for hints or confirmation emails. The Twitter module in holehe/modules/social_media/twitter.py posts to the forgot-password endpoint and inspects the JSON response for a reset_sent flag, populating the field with recovery hints when present.
Phone Number Extraction
When services expose contact information, the phoneNumber field enables phone-number extraction. After confirming account existence, modules parse HTML or JSON responses for disclosed phone numbers linked to the target email address.
Additional Metadata Harvesting
The others dictionary supports additional metadata extraction, capturing supplementary data such as full names, account creation dates, or profile details scraped from the service's response. This field aggregates any user information beyond basic existence confirmation.
Rate Limit Detection
The rateLimit boolean implements rate-limit detection, identifying when services throttle requests with "too many requests" responses or similar HTTP 429 status codes. This prevents false negatives and signals when to adjust request timing.
Error State Handling
The error flag provides error handling for unexpected HTTP failures, parsing exceptions, or malformed responses that prevent conclusive determination of account status.
Practical Implementation Examples
The following examples demonstrate how different services implement these detection methods using service-specific logic and the httpx asynchronous client.
Twitter (Social Media)
The Twitter module in holehe/modules/social_media/twitter.py utilizes the password-recovery endpoint to verify registration. It sends a POST request to the forgot-password API and evaluates the JSON response for reset confirmation, setting both exists and emailrecovery fields accordingly.
# Simplified module pattern (e.g., holehe/modules/social_media/twitter.py)
async def twitter(email, client, out):
resp = await client.post(
"https://api.twitter.com/account/forgot_password",
json={"email": email},
)
if resp.json().get("reset_sent"):
out.append({
"name": "twitter",
"domain": "twitter.com",
"exists": True,
"emailrecovery": "Reset link sent",
"phoneNumber": None,
"others": None,
"rateLimit": False,
"error": False,
})
else:
# handle not-found / rate-limit / error cases similarly
pass
Instagram (Social Media)
Located in holehe/modules/social_media/instagram.py, this module sends POST requests to the reset password API. It distinguishes between "email not found" and "reset link sent" messages to populate the exists and emailrecovery fields, demonstrating how different services require unique response parsing logic.
GitHub (Programming)
The GitHub implementation in holehe/modules/programing/github.py performs an unauthenticated query to the users API. Unlike social media modules that rely on password recovery flows, this module uses direct API inspection, setting exists based strictly on HTTP status codes (200 vs 404).
Amazon (Shopping)
In holehe/modules/shopping/amazon.py, the module accesses the login page and searches for hidden form fields that reveal whether the supplied email is recognized by the system, populating both exists and occasionally emailrecovery data.
Module Architecture and HTTP Execution
All modules follow an asynchronous pattern using the httpx library for non-blocking HTTP requests. Each module receives the target email and an HTTP client instance, executes service-specific logic to implement one or more detection methods, and returns the standardized dictionary. The core engine in holehe/core.py aggregates these results concurrently, utilizing holehe/instruments.py for progress tracking and holehe/localuseragent.py for randomized user-agent strings.
Summary
- Holehe modules implement six standardized holehe detection methods: existence checks, password-recovery probing, phone-number extraction, metadata harvesting, rate-limit detection, and error handling.
- The result schema defined in
holehe/core.pyenforces consistency across all modules, with fields includingexists,emailrecovery,phoneNumber,others,rateLimit, anderror. - Service-specific implementations vary by endpoint type, ranging from direct API queries (GitHub) to password-reset flows (Twitter, Instagram) and HTML form analysis (Amazon).
- All modules operate asynchronously via httpx, returning standardized dictionaries that the central orchestrator aggregates for comprehensive email OSINT reporting.
Frequently Asked Questions
What is the primary detection method used by most Holehe modules?
Most modules rely on password-recovery probing as the primary detection method. By triggering "forgot password" flows and analyzing response messages, modules can verify account existence without attempting authentication, as implemented in holehe/modules/social_media/twitter.py and instagram.py.
How does Holehe handle services that throttle or block requests?
Modules implement rate-limit detection through the rateLimit boolean field. When a service returns HTTP 429 status codes or "too many requests" messages, the module sets this flag to True, allowing the core engine to distinguish between non-existent accounts and temporarily blocked queries.
Can Holehe modules extract personal information beyond email verification?
Yes, through additional metadata extraction captured in the others dictionary field. Modules may scrape full names, account creation dates, or other profile details from service responses, while the phoneNumber field specifically captures disclosed phone numbers when available in password-recovery or account details responses.
Where is the detection logic implemented in the Holehe codebase?
Detection logic resides in individual module files under holehe/modules/ (organized by category such as social_media/, programing/, and shopping/), while the standardized result schema and aggregation logic are defined in holehe/core.py lines 35-48 and 67-78.
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 →