How to Integrate Holehe as a Python Library: Complete Developer Guide
You can integrate Holehe as a Python library by importing the core discovery functions from holehe.core, instantiating an httpx.AsyncClient, and executing service coroutines concurrently through trio.open_nursery().
Holehe is an open-source OSINT tool that verifies email address registrations across hundreds of websites and services. While it provides a command-line interface, the megadose/holehe repository is architected as a modular Python package that allows you to integrate Holehe as a Python library within your own async applications. The library leverages trio for structured concurrency and httpx for HTTP transport, returning standardized result dictionaries for each platform check.
Architecture Overview
Core Engine and Module Discovery
The library’s entry point resides in holehe/core.py, which exposes two critical helper functions for programmatic use. The import_submodules() function (lines 37-47) dynamically walks the holehe.modules package to load every available service module. Subsequently, get_functions() (lines 50-63) filters these loaded modules into a list of callable coroutines that implement the email-lookup API. This design allows the engine to automatically discover new services as they are added to the holehe/modules/ directory without requiring manual registration.
Service Module Interface
Each individual service module (e.g., holehe/modules/social_media/snapchat.py) exports a single async coroutine following the strict signature async def <service_name>(email, client, out). The email parameter receives the target string, client is a shared httpx.AsyncClient instance for connection pooling, and out is a mutable list where the coroutine appends a standardized dictionary containing keys like name, domain, exists, emailrecovery, and phoneNumber. All I/O is asynchronous, ensuring efficient concurrent execution across hundreds of services.
Installation and Prerequisites
Add Holehe to your project dependencies via pip:
pip install holehe
For development or to pin a specific version, install directly from the megadose/holehe repository:
git clone https://github.com/megadose/holehe.git
cd holehe && pip install .
The library requires trio and httpx as core dependencies. If you intend to embed Holehe within an existing asyncio codebase, you will also need trio-asyncio as detailed in the compatibility section below.
Running the Full Email Scan Suite
To execute a complete check across all available modules, use the discovery helpers followed by a trio nursery for concurrency. The following example demonstrates the canonical integration pattern:
import trio
import httpx
from holehe.core import import_submodules, get_functions, print_result
async def scan_email(email: str):
# Discover all modules under holehe.modules
modules = import_submodules("holehe.modules")
websites = get_functions(modules)
# Initialize async HTTP client with appropriate timeout
client = httpx.AsyncClient(timeout=10)
out = []
# Execute all checks concurrently
async with trio.open_nursery() as nursery:
for site in websites:
nursery.start_soon(site, email, client, out)
await client.aclose()
# Display results using Holehe's built-in formatter
class Args:
nocolor = False
noclear = True
onlyused = False
print_result(out, Args(), email, start_time=0, websites=websites)
# Run the scan
trio.run(scan_email, "target@example.com")
This approach loads every module found in the holehe/modules directory, aggregates the callable functions, and runs them simultaneously. The mutable out list collects results from all coroutines, preserving the order of completion.
Targeting Individual Services
For applications requiring only specific platforms (e.g., to reduce network traffic or execution time), import and call individual modules directly:
import trio
import httpx
from holehe.modules.social_media.snapchat import snapchat
async def check_single_service(email: str):
client = httpx.AsyncClient(timeout=10)
results = []
await snapchat(email, client, results)
await client.aclose()
# results contains: [{'name': 'snapchat', 'domain': 'snapchat.com', 'exists': True, ...}]
return results
trio.run(check_single_service, "user@example.com")
Selective importing bypasses the discovery overhead of import_submodules() and gives you fine-grained control over which services to query.
Asyncio Compatibility
Although Holehe is built on trio, you can embed it within asyncio applications using the trio_asyncio bridge. Install the compatibility layer (pip install trio-asyncio) and open a trio loop inside your async function:
import asyncio
import trio_asyncio
import httpx
from holehe.modules.social_media.twitter import twitter
async def asyncio_wrapper(email: str):
async with trio_asyncio.open_loop():
client = httpx.AsyncClient(timeout=10)
out = []
await twitter(email, client, out)
await client.aclose()
return out
# Run within existing asyncio event loop
results = asyncio.run(asyncio_wrapper("test@example.com"))
This pattern allows you to integrate Holehe into legacy asyncio codebases or frameworks like FastAPI or Sanic without migrating your entire application to trio.
Exporting Results Programmatically
Holehe provides utility functions for formatting and exporting results. To generate a CSV file instead of console output, use the export_csv function from holehe.core:
from holehe.core import export_csv
# Assuming 'out' contains results from a scan
class CsvConfig:
csvoutput = True
export_csv(out, CsvConfig(), email="user@example.com")
# Creates: holehe_<timestamp>_user@example.com_results.csv
The CSV export function handles timestamping and file naming conventions automatically, writing the standardized result dictionaries to disk with appropriate headers.
Summary
- Import discovery helpers from
holehe/core.py(import_submodules,get_functions) to dynamically load service modules or import specific modules directly for targeted checks. - Use
httpx.AsyncClientfor connection pooling and pass it along with a mutable results list to each service coroutine. - Execute via
triousingtrio.open_nursery()for true concurrency across hundreds of services. - Bridge to
asynciousingtrio_asynciowhen integrating into existing asyncio applications. - Consume standardized dictionaries containing
name,domain,exists, and optional recovery data to drive downstream logic.
Frequently Asked Questions
Can I run Holehe inside an existing asyncio application without migrating to trio?
Yes, you can integrate Holehe as a Python library within asyncio codebases by using the trio-asyncio compatibility package. Wrap the Holehe execution in an async with trio_asyncio.open_loop() context manager to spawn a trio event loop inside your asyncio routine.
How do I limit the scan to specific websites instead of running all modules?
Instead of calling import_submodules and get_functions, directly import the specific modules you need from the holehe.modules package (e.g., from holehe.modules.social_media.snapchat import snapchat). Pass the coroutine directly to the nursery or await it individually with your httpx.AsyncClient and results list.
What data structure does each service return?
Each service appends a standardized dictionary to the shared out list with keys including name (service identifier), domain (service domain), exists (boolean indicating if the email is registered), emailrecovery (partial recovery email if exposed), and phoneNumber (partial phone if exposed). The schema is consistent across all modules in the megadose/holehe repository.
Where is the CLI entry point defined if I want to wrap or extend it?
The command-line interface is implemented as a thin wrapper in holehe/core.py (lines 32-34). It parses arguments and invokes trio.run(maincore). You can import maincore or the helper functions directly to build custom CLI tools that leverage the same underlying engine without shelling out to the command line.
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 →