How the Register Detection Method Works in holehe: Email Enumeration via Registration Flows
The register detection method in holehe simulates a new user registration attempt on target services and analyzes HTTP responses for indicators—such as error messages or specific status codes—that confirm whether an email address is already associated with an existing account.
holehe is an open-source Python tool for email footprinting that checks whether an address is registered across hundreds of online services. Each service module in the repository declares a method attribute that dictates its enumeration strategy. When this attribute is set to "register", the module exploits the service's public registration endpoint to infer account existence without requiring authentication.
How the Core Engine Dispatches Register Checks
In holehe/core.py, the engine dynamically imports every Python file located in holehe/modules/** and instantiates service-specific classes. Each class exposes a class-level attribute named method. When the core encounters method = "register", it routes execution to the registration-based enumeration logic rather than password-reset or login-based alternatives.
Module Discovery and Method Selection
The core buildsa dictionary mapping service names to module instances. For each imported module, the engine inspects the method attribute:
# Conceptual flow from holehe/core.py
for module in load_modules('holehe/modules/'):
if module.method == "register":
tasks.append(module.run(client, email))
This dispatch mechanism allows holehe to treat registration-based checks as a distinct category requiring specific request patterns: retrieving registration pages, extracting anti-CSRF tokens, and submitting form data.
Asynchronous Request Execution
The core initializes an httpx.AsyncClient (provided by holehe/instruments.py) to maintain session state across requests. For register modules, the typical execution flow involves three phases:
- Token Extraction: A GET request to the registration URL retrieves hidden form fields, CSRF tokens, and session cookies.
- Form Submission: A POST request sends the target email address alongside dummy data (passwords, usernames) that passes client-side validation but triggers server-side email uniqueness checks.
- Header Mimicry: Requests include realistic headers such as
User-Agent,Referer,Accept-Language, andContent-Typeto avoid bot detection.
Response Analysis and Detection Logic
After submitting the registration form, the module analyzes the server response through multiple vectors to determine if the email exists in the target database.
Identifying Registered Accounts via HTTP Responses
The run coroutine in each module implements response parsing logic that looks for three specific indicators:
- Status Code Analysis: HTTP 422 (Unprocessable Entity), 409 (Conflict), or custom status codes specific to the platform that indicate validation failures.
- Text Pattern Matching: Case-insensitive searches for strings like "already registered", "email is already used", "that email is taken", or "account already exists" within
response.text. - JSON Field Inspection: For API-based registration endpoints, parsing the JSON body for error keys such as
{"error": "already_exists"},{"success": false, "code": "duplicate_email"}, or similar schema markers indicating the email is in use.
Returning Enumeration Results
The module's run method returns a structured result—typically a boolean or dictionary—that the core aggregates into the final report. For example:
# Typical return pattern from holehe/modules/ example
if "already registered" in post_resp.text.lower() or post_resp.status_code == 422:
return {"name": "ExampleService", "exists": True, "email": email}
return {"name": "ExampleService", "exists": False, "email": email}
Implementation Example: Anatomy of a Register Module
The following code illustrates the pattern used across holehe/modules/**/*.py when implementing the register detection method:
# Located at holehe/modules/example_platform.py
import httpx
from holehe.instruments import get_random_user_agent
class ExamplePlatform:
method = "register"
url = "https://example.com/signup"
async def run(self, client: httpx.AsyncClient, email: str):
headers = {
"User-Agent": get_random_user_agent(),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
}
# Step 1: Retrieve registration form and tokens
get_resp = await client.get(self.url, headers=headers)
csrf_token = extract_csrf_token(get_resp.text) # Custom parsing logic
# Step 2: Simulate registration attempt
payload = {
"email": email,
"password": "DummyPassword123!",
"confirm_password": "DifferentPass123!", # Intentional mismatch to prevent actual creation
"csrf_token": csrf_token,
"terms": "false" # Fail additional checks
}
post_resp = await client.post(
self.url,
data=payload,
headers={**headers, "Content-Type": "application/x-www-form-urlencoded"}
)
# Step 3: Analyze response for existence indicators
if post_resp.status_code == 400 and "email already exists" in post_resp.text.lower():
return {"exists": True, "service": "ExamplePlatform"}
return {"exists": False, "service": "ExamplePlatform"}
Why Registration-Based Enumeration Is Effective
Public registration endpoints must validate email uniqueness before creating accounts, making them reliable indicators of account existence. Unlike login endpoints—which often return ambiguous errors for "user not found" versus "wrong password"—registration forms typically provide explicit confirmation when an email is already registered. By reproducing the exact request sequence a browser would send, holehe bypasses the need for API keys or authenticated sessions while leveraging the service's own validation logic.
Summary
- Register Method: Simulates account creation attempts to probe for existing emails without completing actual registration.
- Module Declaration: Service modules declare
method = "register"in files underholehe/modules/**/*.pyto opt into this strategy. - Core Orchestration:
holehe/core.pyimports modules, checks for the register method, and coordinates asynchronous execution viahttpx.AsyncClient. - Detection Mechanism: Analysis relies on HTTP status codes (422, 409), plain-text error markers ("already registered"), and JSON error fields from registration endpoints.
- Session Management:
holehe/instruments.pyprovides utilities for maintaining sessions and generating realistic request headers.
Frequently Asked Questions
What is the difference between the register method and other detection methods in holehe?
Other methods may exploit password reset flows or login error messages to infer account existence. The register method specifically targets the account creation endpoint, which often provides binary "email already exists" responses rather than ambiguous authentication failures.
How does holehe handle CSRF tokens and session cookies during register checks?
According to holehe/instruments.py, the tool maintains persistent sessions via httpx.AsyncClient. Each registration module first performs a GET request to the target's registration page to extract anti-CSRF tokens and session cookies, then includes these values in the subsequent POST request to ensure the registration attempt appears legitimate.
Can the register detection method trigger actual account creation?
No. Modules using the register method are designed to halt before final submission or employ intentionally invalid secondary data—such as mismatched password confirmations or declined terms-of-service agreements—that passes email format validation but fails subsequent business logic checks. The tool only captures the immediate server response regarding email uniqueness.
Which file contains the main orchestration logic for the register method?
The primary dispatch logic resides in holehe/core.py, which dynamically imports modules from holehe/modules/, inspects the method class attribute for the value "register", and coordinates the asynchronous execution of each service's run coroutine while aggregating results into the final enumeration report.
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 →