Holehe Async Module Function Signature: The Standardized API for Email OSINT
Every asynchronous module function in the Holehe repository follows the exact signature async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None, enabling uniform email existence checks across 60+ services.
Holehe is an open-source OSINT tool that checks where an email address is registered online. Its architecture relies on a modular design where each service interrogator lives in its own Python file under holehe/modules/. To allow the core runner to execute dozens of checks concurrently without custom logic for each site, every module exposes an identical asynchronous function signature.
The Universal Three-Parameter Pattern
According to the source code in megadose/holehe, all public module functions implement this strict interface:
async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None
The parameters serve distinct roles:
email– The target address to probe, passed as a standard Python string.client– Anhttpx.AsyncClient(or compatible) instance, typically pre-configured with random user-agents fromholehe/localuseragent.pyand optional proxy settings.out– A mutable list passed by reference that the function appends a result dictionary to. This dictionary contains keys such asname,domain,method,exists,rateLimit, anderror.
This signature appears consistently across all module categories, from social media scanners in holehe/modules/social_media/twitter.py to shopping platforms in holehe/modules/shopping/amazon.py.
Module Categories and File Structure
The repository organizes modules into 20 functional categories. While each file contains unique logic for bypassing CSRF tokens or parsing JSON responses, the function signature remains invariant.
Social Media and Communication
Services checking major platforms follow the standard signature:
holehe/modules/social_media/twitter.py:async def twitter(email, client, out)holehe/modules/social_media/instagram.py:async def instagram(email, client, out)holehe/modules/social_media/discord.py:async def discord(email, client, out)holehe/modules/social_media/facebook.py:async def facebook(email, client, out)
Software and Development
Programming-related services use the same interface:
holehe/modules/programing/github.py:async def github(email, client, out)holehe/modules/programing/replit.py:async def replit(email, client, out)holehe/modules/programing/codecademy.py:async def codecademy(email, client, out)holehe/modules/software/docker.py:async def docker(email, client, out)holehe/modules/software/adobe.py:async def adobe(email, client, out)
Shopping and E-commerce
Commercial platforms adhere to the pattern:
holehe/modules/shopping/amazon.py:async def amazon(email, client, out)holehe/modules/shopping/ebay.py:async def ebay(email, client, out)holehe/modules/shopping/deliveroo.py:async def deliveroo(email, client, out)
Additional Categories
The uniform signature extends to niche categories including:
- Music:
spotify,soundcloud,lastfminholehe/modules/music/ - Productivity:
evernote,anydoinholehe/modules/productivity/ - Medical:
caringbridge,sevencupsinholehe/modules/medical/ - Payment:
venmoinholehe/modules/payment/venmo.py
Internal Helper Functions vs. Public API
While the public-facing module functions maintain the strict three-parameter contract, some modules define internal async helpers with extended signatures for multi-step authentication flows. For example, holehe/modules/products/samsung.py contains get_phone_number, which accepts additional cookies and headers parameters. These helpers are implementation details used within the file and are not called by the core runner.
How holehe/core.py Leverages the Signature
The uniformity of the async module function signature enables the orchestration logic in holehe/core.py to discover and execute modules dynamically. The runner introspects the holehe/modules/ directory, imports each function, and schedules concurrent tasks using asyncio.gather() without branching logic:
# Conceptual flow from holehe/core.py
tasks = []
for module_function in discovered_modules:
tasks.append(module_function(email, client, results_list))
await asyncio.gather(*tasks)
Because every function accepts client and out identically, the core engine shares a single httpx.AsyncClient instance across all checks and aggregates results into a single list efficiently.
Practical Example: Direct Module Invocation
You can import and call any module function directly when building custom workflows, provided you supply the three required arguments:
import httpx
import asyncio
from holehe.modules.social_media.twitter import twitter
async def check_twitter():
async with httpx.AsyncClient() as client:
results = []
await twitter("target@example.com", client, results)
# results now contains: [{'name': 'twitter', 'exists': True/False, ...}]
print(results)
asyncio.run(check_twitter())
This pattern works identically for any module in the repository, from holehe/modules/mails/google.py to holehe/modules/porn/pornhub.py.
Summary
- Standard signature: All async module functions use
async def func(email, client, out). - Location: Modules reside in categorized subdirectories under
holehe/modules/. - Parameters:
email(str),client(httpx.AsyncClient), andout(list). - Return value:
None; results are appended to the mutableoutlist. - Internal helpers: Some modules define private functions with extra parameters, but these are not part of the public API consumed by
holehe/core.py.
Frequently Asked Questions
What is the exact async function signature for Holehe modules?
Every module exposes async def <service_name>(email: str, client: httpx.AsyncClient, out: list) -> None. This signature is enforced across all 60+ services, allowing the core runner to invoke each function without custom adapters.
Why does Holehe use a mutable list instead of returning values?
The out list parameter enables safe concurrent aggregation. When asyncio.gather() runs dozens of module functions simultaneously, each appends its result dictionary to the shared list without race conditions, avoiding the need for complex return-value collation logic in holehe/core.py.
Can I use a different HTTP client instead of httpx.AsyncClient?
The type hint specifies httpx.AsyncClient, but any compatible async client implementing .get(), .post(), and similar coroutine methods will work, provided it supports the same interface. However, the official holehe distribution pre-configures httpx.AsyncClient instances with randomized user-agents from holehe/localuseragent.py.
How do I add a custom module to Holehe?
Create a Python file in the appropriate holehe/modules/<category>/ subdirectory. Define an async function matching the standard signature (email, client, out), append your result dictionary to out, and ensure the function name matches the service identifier. The auto-discovery mechanism in holehe/core.py will include it automatically on the next run.
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 →