Holehe Module Signature: Standard Async Interface for Email Osint Modules

Holehe modules follow a strict three-argument async signature: async def module_name(email, client, out) where email is the target address, client is an httpx.AsyncClient instance, and out is a mutable list for result dictionaries.

Holehe is an open-source email osint (open source intelligence) tool by megadose that checks whether an email address is registered on hundreds of platforms. Its modular architecture depends on a uniform callable interface that every service-specific module must implement. Understanding this Holehe module signature is essential for contributors building new modules or developers integrating Holehe into their own pipelines.

The Standard Three-Argument Signature

Every Holehe module is implemented as an asynchronous function with exactly three positional parameters. This contract is enforced by the core engine in holehe/core.py when it discovers and invokes modules.

async def <module_name>(email, client, out):

Parameter Breakdown

Parameter Type Purpose
email str The target email address to verify on the service
client httpx.AsyncClient Async HTTP client for making web requests without blocking
out list Mutable result container; modules append their findings as dictionaries

This signature appears identically across all modules, from holehe/modules/transport/blablacar.py to holehe/modules/software/office365.py. The core orchestrator relies on this consistency to load modules dynamically and execute them concurrently.

Required Result Dictionary Structure

Modules append a standardized dictionary to the out list. According to the source code in existing modules like blablacar.py, this dictionary must contain these keys:

  • name — Internal module identifier (typically matching the function name)
  • domain — Domain being probed (e.g., blablacar.com, office365.com)
  • method — Interaction type: "register", "login", or "other"
  • frequent_rate_limit — bool indicating if the service aggressively rate-limits
  • rateLimit — True if the current request was throttled
  • exists — bool indicating whether the email is registered on the service

Optional fields provide additional osint data:

  • emailrecovery — Secondary email recovered from the service
  • phoneNumber — Phone number associated with the account
  • others — Service-specific metadata as a dictionary

Implementing and Calling a Holehe Module

Direct Module Invocation

You can import and call individual modules directly when testing or building selective checks:

import asyncio
import httpx
from holehe.modules.transport.blablacar import blablacar

async def check_blablacar(email: str) -> dict:
    async with httpx.AsyncClient() as client:
        out = []
        await blablacar(email, client, out)
        return out[0]  # Single result dict for this service

result = asyncio.run(check_blablacar("example@example.com"))
print(result)

This pattern mirrors exactly how the core engine invokes modules, passing the same three arguments.

Full Scanner Integration

The run_modules function in holehe/core.py iterates all registered modules using this signature:

import asyncio
import httpx
from holehe.core import run_modules  # Core orchestrator

async def scan_email(email: str):
    async with httpx.AsyncClient() as client:
        results = await run_modules(email, client)  # Calls each module with (email, client, out)

        for r in results:
            print(f"{r['name']}: exists={r['exists']}")

asyncio.run(scan_email("example@example.com"))

The core loader discovers modules via holehe/modules/__init__.py, then instantiates each with the standard email, client, out signature.

Key Source Files Defining the Contract

File Role in Module Signature
holehe/core.py Implements run_modules() that enforces the three-argument call pattern
holehe/modules/__init__.py Registers all modules for dynamic discovery
holehe/modules/transport/blablacar.py Reference implementation showing proper signature usage
holehe/modules/software/office365.py Alternative module demonstrating the same interface
holehe/localuseragent.py Supplies ua dictionary for User-Agent rotation in requests

These files collectively establish the Holehe module signature as a rigid contract. Any deviation prevents proper integration with the core engine.

Summary

  • Holehe module signature requires exactly three arguments: email, client, and out
  • All modules must be async functions to enable non-blocking concurrent execution
  • Results are appended to out as dictionaries with mandatory keys: name, domain, method, frequent_rate_limit, rateLimit, and exists
  • The core engine in holehe/core.py depends on this uniformity for module discovery and orchestration
  • Reference implementations in blablacar.py and office365.py demonstrate proper adherence to the contract

Frequently Asked Questions

What happens if a Holehe module doesn't follow the standard signature?

The core engine in holehe/core.py will fail to invoke the module correctly. Modules are called with positional arguments (email, client, out), so any deviation in parameter count or order causes a TypeError. The module discovery mechanism in holehe/modules/__init__.py assumes all registered functions conform to this interface.

Can I use a different HTTP client instead of httpx.AsyncClient?

No. The client parameter is always an httpx.AsyncClient instance passed by the core engine. Modules rely on its specific API (get, post, headers manipulation). Replacing it would break compatibility with existing modules and the core runner.

Is the out list strictly necessary, or can modules return values directly?

The out list is mandatory. Holehe's concurrent execution model uses mutable containers to collect results from multiple async tasks. Modules must append their result dictionary to out rather than returning values, as shown in blablacar.py and all other reference implementations.

Which key in the result dictionary indicates successful account discovery?

The exists boolean determines whether the email is registered. A value of True confirms the account exists on the service; False means unregistered or indeterminate. This is the primary output consumers check when aggregating Holehe results across multiple services.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →