How to Use Holehe Programmatically in Python: Async Email Reconnaissance
Holehe can be used programmatically in Python by importing the asynchronous check modules from the megadose/holehe repository and executing them with an HTTPX client, or by calling the high-level main() function from holehe.core to replicate CLI behavior.
Holehe is a pure-Python library designed for email reconnaissance across social media and web platforms. Unlike tools that require shell execution, Holehe exposes its internal machinery for direct Python integration, allowing security researchers to embed email existence checks directly into async workflows without spawning external processes.
Understanding Holehe's Async Architecture
At the heart of Holehe lies an asynchronous architecture built on Trio and HTTPX. The entry point resides in holehe/core.py, where the main() function initializes the async event loop by calling trio.run(maincore).
The maincore() function orchestrates the entire workflow: it parses arguments, instantiates an httpx.AsyncClient, and dynamically loads every available check module using import_submodules("holehe.modules"). Each module is then executed as a separate async task via launch_module, enabling concurrent checks against multiple platforms.
Individual check modules follow a strict contract. Each exposes an async function accepting three parameters: email, client (an HTTPX instance), and out (a list to collect results). For example, holehe/modules/social_media/snapchat.py implements async def snapchat(email, client, out) to query Snapchat's endpoints.
Running Single Module Checks
For targeted investigations, you can import and execute specific modules without loading the entire library. This approach minimizes overhead when you only need to verify an email against a single platform.
Importing Specific Check Modules
The following example demonstrates checking a single email against Snapchat using the raw module interface:
import trio
import httpx
from holehe.modules.social_media.snapchat import snapchat
async def demo():
email = "test@example.com"
out = []
async with httpx.AsyncClient() as client:
await snapchat(email, client, out)
print(out)
trio.run(demo)
The out list receives a standardized dictionary containing fields such as name, exists, emailrecovery, and rateLimit. This format remains consistent across all modules in the holehe.modules namespace.
Orchestrating Full Email Scans
To execute comprehensive reconnaissance across all supported platforms, you must dynamically load the module registry and coordinate concurrent execution using Trio's nursery pattern.
Loading and Executing All Modules
The import_submodules() function discovers all check modules, while get_functions() extracts the callable entry points. The following implementation runs every available check concurrently:
import trio
import httpx
from holehe.core import import_submodules, get_functions, launch_module
async def full_scan(email):
modules = import_submodules("holehe.modules")
websites = get_functions(modules)
async with httpx.AsyncClient() as client:
out = []
async with trio.open_nursery() as nursery:
for mod in websites:
nursery.start_soon(launch_module, mod, email, client, out)
return out
results = trio.run(full_scan, "test@example.com")
for result in results:
print(result)
This pattern creates an httpx.AsyncClient session shared across all checks, then spawns each module as a separate task within a Trio nursery. The launch_module wrapper handles execution and appends standardized results to the shared out list.
Using the High-Level CLI Wrapper
When you need behavior identical to the command-line interface without shelling out, invoke the main() function directly from holehe.core.
Replicating CLI Behavior in Python
This approach handles argument parsing, client initialization, and result formatting automatically:
from holehe.core import main
if __name__ == "__main__":
main()
Calling main() executes trio.run(maincore), which processes sys.argv exactly as the holehe console script would. This is ideal for scripting scenarios where you want the full suite of checks with standard output formatting, but need to trigger it from within a larger Python application.
Key Source Files and Functions
Understanding these core components enables advanced customization of Holehe's behavior:
-
holehe/core.py— Containsmain(),maincore(),import_submodules(), andlaunch_module(). This file manages module discovery, async orchestration, and the HTTP client lifecycle. -
holehe/modules/— Directory containing platform-specific implementations. Each submodule follows theasync def <name>(email, client, out)signature. -
holehe/modules/social_media/snapchat.py— Reference implementation showing the request construction pattern and result dictionary formatting used throughout the library. -
Result Schema — Every module returns a dictionary with standardized keys including
name(service identifier),exists(boolean),emailrecovery(partial email hints), andrateLimit(status indicator).
Summary
- Holehe exposes a pure-Python API that eliminates the need for subprocess calls or shell interactions.
- The library uses Trio for async concurrency and HTTPX for HTTP transport, with the main orchestration logic in
holehe/core.py. - Individual modules can be imported directly from
holehe.modulesfor targeted checks using theasync def(email, client, out)interface. - Full reconnaissance scans utilize
import_submodules()andget_functions()to dynamically load all checks, executed concurrently vialaunch_module()in a Trio nursery. - The
main()function provides a synchronous entry point that replicates CLI behavior while handling async execution internally.
Frequently Asked Questions
Can I run Holehe synchronously without using Trio directly?
Yes. Import and call main() from holehe.core to execute the full Holehe workflow synchronously. This function internally calls trio.run(maincore), managing the event loop creation and teardown automatically while processing command-line arguments from sys.argv.
What dependencies are required for programmatic usage?
Holehe requires Trio for asynchronous orchestration and HTTPX for HTTP requests. These are specified in the repository's requirements. When importing modules directly, ensure you have an active HTTPX async client to pass to the check functions.
How do I interpret the results returned by Holehe modules?
Each module appends a dictionary to the provided out list containing standardized fields: name (the service checked), exists (boolean indicating account existence), emailrecovery (partial email hints if exposed), phoneNumber (masked phone if exposed), and rateLimit (boolean indicating throttling status).
Is it possible to add custom check modules to Holehe?
Yes. Create a Python file in the holehe.modules namespace implementing the standard async signature async def your_module(email, client, out). The import_submodules() function in holehe/core.py automatically discovers any module in this namespace, allowing get_functions() to include your custom checks in full scans.
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 →