How to Use Holehe Programmatically to Check Multiple Modules: A Complete Guide
You can use Holehe programmatically by importing its async core functions from holehe/core.py, which automatically discover all detection modules and run them concurrently with Trio and httpx.
Holehe is an open-source OSINT tool for email account discovery across hundreds of services. While it provides a CLI, its true power lies in the Python API exposed through holehe/core.py. This guide shows you how to embed Holehe in your own scripts to check single modules, run everything, or cherry-pick specific services.
Understanding Holehe's Async Architecture
Holehe follows a lightweight asynchronous design built around three core concepts: dynamic module discovery, consistent coroutine signatures, and Trio-based concurrency.
Module Discovery in holehe/core.py
The function import_submodules("holehe.modules") walks the entire holehe/modules/ package tree and imports every Python file. The helper get_functions() then extracts the public coroutine from each module—typically named after the service (e.g., twitter, snapchat)【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L37-L64】.
This means new modules added to the repository are automatically available without code changes.
Standardized Module Interface
Every detection module implements the same async signature:
async def service_name(email: str, client: httpx.AsyncClient, out: list) -> None:
# Queries the service and appends result dict to `out`
The launch_module() wrapper in holehe/core.py handles exceptions and converts them to standardized result objects, ensuring uniform output regardless of individual module failures【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L66-L78】.
Concurrent Execution with Trio
A Trio nursery spawns all modules simultaneously. The TrioProgress instrument attaches to Trio's low-level instrumentation for progress tracking【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L16-L22】. Results are collected into a shared list, then sorted and processed【/cache/repos/github.com/megadose/holehe/master/holehe/core.py#L124-L131】.
Running a Single Module Manually
For targeted checks, import and call any module directly. Here's the Snapchat module in action:
import trio
import httpx
from holehe.modules.social_media.snapchat import snapchat
async def demo_one():
email = "test@example.com"
out = []
client = httpx.AsyncClient()
await snapchat(email, client, out)
print(out)
await client.aclose()
trio.run(demo_one)
Each module file lives under holehe/modules/ by category. For example, the Twitter check is implemented in holehe/modules/social_media/twitter.py【/cache/repos/github.com/megadose/holehe/master/holehe/modules/social_media/twitter.py#L5-L37】.
Running All Available Modules Automatically
To execute every discovered service concurrently, use Holehe's core orchestration:
import trio
import httpx
from holehe.core import import_submodules, get_functions, launch_module, TrioProgress
async def demo_all():
email = "test@example.com"
# 1. Discover every detection module
modules = import_submodules("holehe.modules")
# 2. Convert to list of callable coroutines
websites = get_functions(modules)
client = httpx.AsyncClient()
out = []
# Optional: add progress bar
instrument = TrioProgress(len(websites))
trio.lowlevel.add_instrument(instrument)
# 3. Launch all modules concurrently
async with trio.open_nursery() as nursery:
for website in websites:
nursery.start_soon(launch_module, website, email, client, out)
trio.lowlevel.remove_instrument(instrument)
await client.aclose()
# Sort results alphabetically by service name
out = sorted(out, key=lambda i: i["name"])
print(out)
trio.run(demo_all)
This pattern is exactly how Holehe's CLI operates. The launch_module wrapper ensures failures in one module don't crash the entire run.
Selecting a Custom Subset of Modules
When you need specific services rather than everything, import modules individually and invoke them directly:
import trio
import httpx
from holehe.modules.social_media.twitter import twitter
from holehe.modules.social_media.instagram import instagram
async def demo_subset():
email = "test@example.com"
out = []
client = httpx.AsyncClient()
for fn in (twitter, instagram):
await fn(email, client, out) # sequential execution
await client.aclose()
print(out)
trio.run(demo_subset)
For concurrent execution of a subset, swap the for loop for a Trio nursery with your chosen functions.
Integrating Holehe Results into Pipelines
Each result dictionary contains standardized keys you can process programmatically:
name— service name (e.g., "twitter")domain— service domainmethod— detection technique usedfrequent_rate_limit— boolean indicating rate-limit likelihoodexists— boolean or None for account existenceemailrecovery— partial recovery email if leakedphoneNumber— partial phone if leakedothers— additional metadata
This structure makes Holehe ideal for feeding OSINT data into databases, SIEMs, or custom enrichment workflows.
Key Source Files Reference
| File | Purpose |
|---|---|
holehe/core.py |
Orchestrates discovery, async execution, result aggregation, and CSV export |
holehe/modules/*/*.py |
One file per service—each defines an async detection function |
holehe/instruments.py |
TrioProgress progress-bar implementation |
holehe/localuseragent.py |
Default User-Agent for HTTP requests |
Summary
- Single module: Import directly from
holehe.modules.*and call with(email, client, out). - All modules: Use
import_submodules()andget_functions()fromholehe/core.py, then spawn withlaunch_module()in a Trio nursery. - Custom subset: Import specific modules and invoke them sequentially or concurrently.
- Shared client: Pass one
httpx.AsyncClientinstance to all calls for connection reuse. - Consistent output: Every module appends a standardized dictionary to the
outlist.
Frequently Asked Questions
What Python version does Holehe require?
Holehe requires Python 3.7+ due to its reliance on Trio and httpx.AsyncClient. The async/await syntax and low-level Trio instrumentation used in holehe/core.py depend on modern Python features.
Can I run Holehe without the progress bar?
Yes. Simply omit the TrioProgress instrument creation and the add_instrument/remove_instrument calls. The core functionality in holehe/core.py works without any instrumentation—progress tracking is purely optional UI sugar.
How do I add a custom detection module to Holehe?
Create a new Python file under holehe/modules/ (in an existing or new category folder) with an async function following the signature async def yourservice(email, client, out). The next time import_submodules("holehe.modules") runs, your module will be discovered automatically.
Does Holehe handle rate limits automatically?
Individual modules set a frequent_rate_limit flag in results to warn about rate-limited services, but Holehe does not implement automatic backoff or retry logic. According to the source code in holehe/core.py, failed requests are caught by launch_module() and converted to error result objects without interrupting other modules.
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 →