Can Holehe Be Used Programmatically in Python? 3 Methods to Integrate OSINT Checks
Yes, Holehe can be used programmatically in Python as a pure-Python library with full async support, no subprocess or external binaries required.
Holehe is an open-source email OSINT tool by megadose that checks whether an email address is registered on hundreds of websites. While commonly used as a CLI tool, its modular architecture makes it ideal for Python automation, custom pipelines, and integration into larger security workflows.
Why Use Holehe Programmatically?
Running Holehe from Python code unlocks several advantages over CLI usage:
- Custom filtering – Process only specific site categories or result types
- Result transformation – Convert output to JSON, database records, or alerts
- Workflow integration – Embed checks into SIEM pipelines, web apps, or scheduled jobs
- Concurrent control – Fine-tune async execution with Trio primitives
The codebase is structured around a simple contract: every site check is an async function with signature (email, client, out) in holehe/modules/.
Method 1: Check a Single Site Directly
For targeted investigations, import and call individual modules. This is the most lightweight approach.
import trio
import httpx
from holehe.modules.social_media.snapchat import snapchat
async def check_snapchat():
email = "target@example.com"
results = []
async with httpx.AsyncClient() as client:
await snapchat(email, client, results)
print(results)
# [{'name': 'snapchat', 'exists': True, 'emailrecovery': None, ...}]
trio.run(check_snapchat)
Each module in holehe/modules/ follows this pattern. The out list receives standardized result dictionaries containing:
| Key | Meaning |
|---|---|
name |
Site identifier (e.g., "snapchat") |
exists |
Boolean indicating registration found |
emailrecovery |
Partial recovery email if exposed |
rateLimit |
Whether the check hit rate limiting |
Method 2: Run Full Multi-Site Scans
To replicate the complete Holehe behavior programmatically, use the core orchestration utilities from holehe/core.py.
import trio
import httpx
from holehe.core import import_submodules, get_functions, launch_module
async def full_holehe_scan(email):
# Dynamically load all site check modules
modules = import_submodules("holehe.modules")
websites = get_functions(modules) # Extract callable check functions
results = []
async with httpx.AsyncClient() as client:
# Run all checks concurrently with Trio nursery
async with trio.open_nursery() as nursery:
for check_func in websites:
nursery.start_soon(launch_module, check_func, email, client, results)
return results
# Execute scan
output = trio.run(full_holehe_scan, "target@example.com")
for site_result in output:
print(f"{site_result['name']}: {site_result.get('exists', 'unknown')}")
The launch_module wrapper in holehe/core.py handles exceptions and ensures partial failures don't crash the entire scan.
Method 3: Invoke the High-Level CLI Wrapper
For quick scripts that need standard CLI behavior without shelling out, call main() directly.
from holehe.core import main
if __name__ == "__main__":
# Behaves identically to: holehe target@example.com
main()
Important: main() parses sys.argv, so you must set arguments before calling:
import sys
from holehe.core import main
sys.argv = ["holehe", "target@example.com", "--only-used"]
main()
This approach respects all CLI flags including --only-used, --no-clear, and timeout settings.
Key Implementation Files Reference
Understanding these source files helps with custom integrations:
holehe/core.py– Containsmain(),maincore(),import_submodules(),get_functions(), andlaunch_module(). The async orchestration hub.holehe/modules/__init__.py– Package structure enabling dynamic module discovery.holehe/modules/social_media/snapchat.py– Template for individual site checks; shows request construction and response parsing.holehe/localuseragent.py– ProvidesgetUserAgent()for rotating headers.
Async Architecture: Trio and httpx
Holehe is built on Trio for structured concurrency and httpx for HTTP. This matters for programmatic use:
- Never mix asyncio and Trio – Use
trio.run()ortrio's guest mode exclusively - Share the client – Pass one
httpx.AsyncClientto all checks for connection pooling - Nursery-based cancellation – Failed checks cancel cleanly without resource leaks
For sync-only codebases, run Trio in a thread:
import trio
def sync_wrapper(email):
return trio.run(full_holehe_scan, email)
result = sync_wrapper("target@example.com")
Summary
- Holehe is fully importable as a Python library in
megadose/holehe - Three integration patterns: single module, full orchestration, or CLI wrapper
- Core functions in
holehe/core.pyhandle module loading and concurrent execution - Result format is standardized across all 100+ site checks
- No subprocess required – pure Python with Trio/httpx async stack
Frequently Asked Questions
Can I use Holehe with standard asyncio instead of Trio?
No. Holehe is built exclusively on Trio for structured concurrency. While Trio can run as a guest inside asyncio using trio.lowlevel.start_guest_run, the library itself requires Trio primitives. Mixing asyncio coroutines directly will cause runtime errors.
How do I filter results to only show confirmed accounts?
Check the exists key in result dictionaries. When using the programmatic API, filter the output list:
confirmed = [r for r in results if r.get("exists") is True]
The --only-used CLI flag performs this filtering automatically when using main().
Is rate limiting handled automatically?
Partially. Individual modules detect rate limits and set rateLimit: True in results, but retry logic is minimal. For production use, implement exponential backoff between calls or proxy rotation via httpx.AsyncClient configuration.
Can I add custom site checks without modifying the source?
Yes. Create a module matching the (email, client, out) signature and add it to holehe/modules/your_category/. The import_submodules function in holehe/core.py dynamically discovers all modules at runtime, so custom checks integrate automatically.
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 →