Holehe Module Signature: Structure for Asynchronous Email OSINT Checkers
Every Holehe module must be an asynchronous function defined as async def module_name(email, client, out) that accepts an email string, an httpx.AsyncClient instance, and a mutable results list, returning None while appending a standardized result dictionary to the out parameter.
The megadose/holehe repository provides a modular framework for checking email existence across hundreds of online services. To maintain compatibility with the core execution engine, every module must implement a specific asynchronous function signature. Understanding the signature for a Holehe module is essential for contributors adding new OSINT sources or customizing existing checks.
The Required Function Signature
The core engine located in holehe/core.py expects a strict interface that enables uniform invocation across all services. The signature for a Holehe module is:
async def <module_name>(email: str, client: httpx.AsyncClient, out: list) -> None
This convention ensures that the orchestration layer can dynamically load and execute any module without service-specific logic.
Parameter Breakdown
-
email (
str): The target email address being investigated across the target platform. -
client (
httpx.AsyncClient): A pre-configured asynchronous HTTP client that must be used for all network requests. Reusing this client enables connection pooling and ensures uniform timeout and header configuration across the framework. -
out (
list): A mutable list supplied by the core engine that acts as a collector for results. The module must append exactly one dictionary describing the check outcome to this list rather than returning values directly.
Result Dictionary Structure
When appending to the out list, the module must provide a dictionary containing standardized keys that the core engine interprets. According to implementations in holehe/modules/shopping/amazon.py and holehe/modules/social_media/facebook.py, the required structure includes:
- name: Service identifier string (e.g.,
"amazon","google") - domain: The service's primary domain (e.g.,
"amazon.com","gmail.com") - method: The verification methodology used, typically
"login"or"register" - frequent_rate_limit: Boolean indicating whether the service commonly imposes rate limiting
- rateLimit: Boolean indicating whether the current request specifically hit a rate limit
- exists: Boolean indicating whether the email address exists on the target platform
- emailrecovery: String containing recovery email if exposed by the service, otherwise
None - phoneNumber: String containing phone number if exposed by the service, otherwise
None - others: Dictionary or
Nonecontaining additional metadata or alternative identifiers
Implementation Examples from the Codebase
Amazon Module (holehe/modules/shopping/amazon.py)
Real-world implementations follow the signature strictly. In holehe/modules/shopping/amazon.py, the function accepts the three required parameters and uses the injected client for requests:
import random
from holehe.core import *
from holehe.localuseragent import *
async def amazon(email, client, out):
name = "amazon"
domain = "amazon.com"
method = "login"
frequent_rate_limit = False
headers = {"User-agent": random.choice(ua["browsers"]["chrome"])}
try:
# ... HTTP logic using client ...
out.append({
"name": name,
"domain": domain,
"method": method,
"frequent_rate_limit": frequent_rate_limit,
"rateLimit": False,
"exists": True,
"emailrecovery": None,
"phoneNumber": None,
"others": None,
})
except Exception:
out.append({
"name": name,
"domain": domain,
"method": method,
"frequent_rate_limit": frequent_rate_limit,
"rateLimit": True,
"exists": False,
"emailrecovery": None,
"phoneNumber": None,
"others": None,
})
Similar patterns appear in holehe/modules/mails/google.py and holehe/modules/social_media/facebook.py, where each module defines an async function with the identical parameter structure.
Minimal Module Template
For developers creating new services, the minimal compliant structure follows this pattern:
from holehe.localuseragent import ua
import random
async def example(email, client, out):
name = "example"
domain = "example.com"
method = "register"
frequent_rate_limit = False
# Always use the provided client for HTTP requests
# result = await client.get(...)
out.append({
"name": name,
"domain": domain,
"method": method,
"frequent_rate_limit": frequent_rate_limit,
"rateLimit": False,
"exists": True,
"emailrecovery": None,
"phoneNumber": None,
"others": None,
})
Core Engine Integration
The holehe/core.py file orchestrates module execution by importing each module dynamically and invoking its function with the three required arguments. The engine initializes a single httpx.AsyncClient instance and passes it to every module, ensuring efficient connection reuse across hundreds of concurrent checks. By standardizing on the async function signature (email, client, out), the framework decouples the execution logic from individual service implementations, allowing contributors to add new sources without modifying core orchestration code.
Summary
- Every Holehe module must define an asynchronous function with the exact signature
async def module_name(email, client, out). - The function must accept three parameters: the target email string, an httpx.AsyncClient for HTTP requests, and a mutable results list.
- Modules must append a dictionary to the
outlist rather than returning values, using keys likename,domain,exists, andrateLimit. - Real implementations in
holehe/modules/shopping/amazon.pyandholehe/modules/mails/google.pydemonstrate proper client reuse and error handling patterns. - The core engine in
holehe/core.pyrelies on this contract to execute hundreds of modules uniformly without service-specific logic.
Frequently Asked Questions
What happens if a Holehe module returns a value instead of appending to out?
The core engine ignores return values from module functions. If a module returns a dictionary instead of appending it to the out list, the results will be lost and the check will appear to produce no output. Always append results to the out parameter to ensure the core receives the data.
Can I use a different HTTP client instead of the provided httpx.AsyncClient?
No. The client parameter provides a pre-configured httpx.AsyncClient that enables connection pooling and respects global timeout settings defined in holehe/core.py. Creating separate client instances within modules would reduce performance and potentially trigger additional rate limiting on target services.
What is the difference between frequent_rate_limit and rateLimit in the result dictionary?
The frequent_rate_limit key indicates that the service generally imposes strict rate limiting (a static property of the platform), while rateLimit specifically indicates that the current request was blocked or throttled. Set frequent_rate_limit to True for services known to aggressively limit requests, and set rateLimit to True only when the current check encounters a rate limit response.
Where should I place new modules in the Holehe repository?
Place new modules in the appropriate subdirectory under holehe/modules/ based on the service category (e.g., holehe/modules/shopping/ for e-commerce sites, holehe/modules/social_media/ for social platforms). The core engine automatically discovers and imports Python files from these directories, provided they implement the correct function signature.
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 →