How to Use Holehe as a Python Library in Your Applications
You can embed Holehe's email OSINT capabilities directly into Python applications by importing holehe.core and utilizing the import_submodules, get_functions, and launch_module utilities to execute asynchronous checks against 120+ services without invoking the CLI.
Holehe is architected as a pure-Python package within the megadose/holehe repository, designed for programmatic integration beyond its command-line interface. The library exposes its internal workflow engine through holehe/core.py, allowing developers to perform in-process email verification using standard asynchronous patterns. By leveraging these internal APIs, you can incorporate email reconnaissance into web applications, automation frameworks, or data processing pipelines while maintaining full control over execution flow and result handling.
Core Library Architecture
The programmatic interface centers on three orchestration utilities defined in holehe/core.py. import_submodules and get_functions (lines 37-66) dynamically discover service modules and transform them into callable async functions that accept (email, client, out) arguments. launch_module (lines 66-79) executes these functions within a trio nursery, handling exceptions and standardizing outputs into dictionaries containing keys such as name, domain, exists, emailrecovery, phoneNumber, and others.
Installation and Dependencies
Install the package via pip to access the library components. According to setup.py, Holehe requires httpx for asynchronous HTTP requests, trio for structured concurrency, beautifulsoup4 for HTML parsing, and termcolor for terminal output formatting.
pip install holehe
Loading Service Modules Dynamically
Unlike static imports, Holehe uses dynamic module discovery to load its extensive collection of service implementations from the holehe/modules/ directory. The import_submodules function accepts the string "holehe.modules" as an argument and recursively imports every service definition (e.g., holehe.modules.social_media.twitter, holehe.modules.software.lastpass).
from holehe.core import import_submodules
# Load all available service modules
modules = import_submodules("holehe.modules")
Selecting and Executing Services
After loading modules, get_functions(modules, args) extracts the callable service functions, with optional filtering via the args parameter. Each service function follows the signature (email: str, client: httpx.AsyncClient, out: list), accepting the target email, an HTTP client instance, and a shared results list.
from holehe.core import get_functions
import httpx
# Extract callable functions from loaded modules
services = get_functions(modules)
# Initialize async HTTP client
client = httpx.AsyncClient(timeout=10)
Implementation Examples
The following patterns demonstrate how to integrate Holehe into different application architectures using the core utilities.
Full Asynchronous Scan
This example loads all modules and executes them concurrently using trio, gathering results into a standardized list.
import trio
import httpx
from holehe.core import import_submodules, get_functions, launch_module
async def scan_email(email: str):
modules = import_submodules("holehe.modules")
services = get_functions(modules)
client = httpx.AsyncClient(timeout=10)
results = []
async with trio.open_nursery() as nursery:
for service in services:
nursery.start_soon(launch_module, service, email, client, results)
await client.aclose()
return sorted(results, key=lambda x: x["name"])
if __name__ == "__main__":
data = trio.run(scan_email, "target@example.com")
for entry in data:
print(entry)
Synchronous Wrapper for Blocking Contexts
When integrating into synchronous codebases, wrap the async logic using asyncio.run while maintaining the trio nursery internally.
import asyncio
import httpx
from holehe.core import import_submodules, get_functions, launch_module
import trio
def check_email_sync(email: str):
modules = import_submodules("holehe.modules")
services = get_functions(modules)
client = httpx.AsyncClient(timeout=10)
results = []
async def _execute():
async with trio.open_nursery() as nursery:
for svc in services:
nursery.start_soon(launch_module, svc, email, client, results)
await client.aclose()
return results
return asyncio.run(_execute())
# Usage in synchronous script
if __name__ == "__main__":
for result in check_email_sync("user@domain.com"):
print(f"{result['name']}: {result['exists']}")
Targeting Individual Services
For targeted investigations, import specific modules directly from holehe/modules/ and invoke them through launch_module to maintain consistent error handling and output formatting.
import httpx
import trio
from holehe.modules.social_media.twitter import twitter
from holehe.core import launch_module
async def check_twitter_only(email: str):
async with httpx.AsyncClient() as client:
out = []
await launch_module(twitter, email, client, out)
return out[0] if out else None
if __name__ == "__main__":
result = trio.run(check_twitter_only, "specific@example.com")
print(result)
Understanding the Output Schema
Every service function populates the shared out list with dictionaries following a uniform schema defined in the library's core logic. Each result contains name (service identifier), domain (service domain), exists (boolean or None), emailrecovery (recovery email if exposed), phoneNumber (exposed phone if available), and others (additional metadata). The launch_module wrapper ensures failed requests or exceptions generate consistent output rather than crashing the nursery, making the results list safe to iterate for reporting or analysis.
Summary
- Import the core utilities from
holehe/core.pyto accessimport_submodules,get_functions, andlaunch_module. - Load modules dynamically using
import_submodules("holehe.modules")to discover all 120+ service implementations. - Execute asynchronously via
trio.open_nursery()to run checks concurrently with structured concurrency. - Standardize outputs through the
launch_modulewrapper, which guarantees consistent dictionary keys regardless of service-specific implementations. - Integrate anywhere by wrapping the async logic in
asyncio.run()for synchronous applications or calling individual modules for targeted checks.
Frequently Asked Questions
Can I use standard asyncio instead of trio for running Holehe?
Yes. While Holehe's launch_module uses trio.open_nursery() internally for structured concurrency, you can wrap the execution logic in asyncio.run() as shown in the synchronous wrapper example. The trio library handles the concurrent execution internally, while your application code can use standard asyncio patterns to initiate the process.
How do I limit the scan to specific services rather than loading all modules?
Pass a modules dictionary filtered by category or name to get_functions(). Since import_submodules returns a dictionary mapping module names to module objects, you can subset this dictionary before passing it to get_functions(modules, args) to select only specific services (e.g., only social media platforms).
What dependencies must I manage when using Holehe programmatically?
According to setup.py, Holehe requires httpx for HTTP requests, trio for async orchestration, beautifulsoup4 for HTML parsing, and termcolor for output formatting. When you install via pip install holehe, these are automatically resolved, but you must ensure trio remains available for the nursery-based execution in holehe/core.py.
Is it possible to use Holehe in a completely synchronous script without async/await?
While the underlying service checks are inherently asynchronous due to I/O operations, you can encapsulate the entire async workflow in a function and execute it via asyncio.run() or trio.run() from within your synchronous code. This pattern allows the library to manage its async HTTP client and concurrency internally while presenting a blocking interface to the rest of your application.
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 →