How to Directly Import and Use a Holehe Module in Python

Directly import any Holehe service checker as an asynchronous function from holehe.modules.<category>.<service>, then execute it with an httpx.AsyncClient and a mutable results list inside an async runtime like Trio.

Holehe by megadose organizes every email-vetting check as an async function within a nested package hierarchy. While the CLI handles module discovery automatically, you can bypass the command-line interface entirely and import any individual checker directly into your own Python scripts for custom automation workflows.

Understanding the Module Structure

Holehe stores each service implementation as a standalone module under holehe/modules/, categorized by service type such as social_media, shopping, or transport. Each module exports an async function matching the service name.

For example, the Twitter checker resides in holehe/modules/social_media/twitter.py and exports the async function twitter. According to the source code in holehe/core.py (lines 37-48), the package provides a helper called import_submodules to dynamically discover these modules for the CLI, but you can import them statically without touching the discovery logic.

Importing and Running a Single Checker

To use a specific module programmatically, import the async function directly and invoke it with three required arguments: the target email string, an httpx.AsyncClient instance, and an empty list that the function will populate with results.

import trio
import httpx

# Import the specific service function

from holehe.modules.social_media.twitter import twitter

async def check_single_service():
    email = "target@example.com"
    results = []  # Will be mutated by the checker

    
    async with httpx.AsyncClient() as client:
        await twitter(email, client, results)
    
    # results now contains a dictionary with the check outcome

    print(results)

trio.run(check_single_service)

The checker appends a dictionary to the supplied results list in-place rather than returning a value. This design pattern allows the library to aggregate data from multiple concurrent checks efficiently without complex return-value orchestration.

Executing Multiple Modules Programmatically

You can import several checkers from the same category and iterate over them to perform batch lookups against a single email address.

import trio
import httpx

# Import multiple service functions at once

from holehe.modules.social_media import twitter, instagram, github

async def batch_check():
    email = "user@example.com"
    out = []
    
    async with httpx.AsyncClient() as client:
        for service_fn in (twitter, instagram, github):
            await service_fn(email, client, out)
    
    for entry in out:
        print(entry)

trio.run(batch_check)

Every checker in the holehe/modules/ directory follows this identical signature: async def service_name(email: str, client: httpx.AsyncClient, out: list) -> None.

Dynamic Discovery with Core Utilities

If you prefer not to hardcode import statements for each service, leverage the same discovery mechanism the CLI uses. The import_submodules function defined in holehe/core.py (lines 37-48) recursively loads all submodules under holehe.modules, and get_functions converts them into callable references.

import httpx
import trio
from holehe.core import import_submodules, get_functions

async def run_all_services():
    # Dynamically load every module in the package

    modules = import_submodules("holehe.modules")
    functions = get_functions(modules)
    
    email = "scan@example.com"
    out = []
    
    async with httpx.AsyncClient() as client:
        for fn in functions:
            await fn(email, client, out)
    
    print(out)

trio.run(run_all_services)

This approach instantiates every available service checker without manual import statements, useful for comprehensive reconnaissance where you want to check an email against every platform supported by the library.

Summary

  • Module Location: Individual checkers live at holehe.modules.<category>.<service> (e.g., holehe.modules.social_media.twitter).
  • Async Requirement: Every checker is an async coroutine requiring an httpx.AsyncClient for HTTP operations.
  • Results Pattern: Pass an empty list as the third argument; the checker appends outcome dictionaries to this list in-place.
  • Discovery Helper: Use import_submodules from holehe/core.py to dynamically load all modules when you need comprehensive coverage.
  • Runtime: Execute with trio.run() or any asyncio-compatible event loop.

Frequently Asked Questions

How do I install Holehe before importing modules?

Install the package via pip to ensure all dependencies like httpx and trio are available: pip install holehe. This makes the holehe namespace importable in your Python environment and provides access to all submodules under holehe/modules/.

Can I use asyncio instead of Trio to run the checkers?

Yes. The async functions in holehe/modules/ are compatible with any asyncio-compatible runner. While the CLI uses Trio internally, you can substitute trio.run() with asyncio.run() or manually obtain an event loop if your application requires standard asyncio patterns.

Why does the checker modify a list instead of returning a value?

The out list parameter serves as a mutable accumulator. This architectural choice maintains a consistent function signature across all modules while supporting concurrent execution strategies where multiple checkers write results to a shared collection without complex return-value handling.

Where is the import_submodules function defined?

The dynamic module loader is implemented in holehe/core.py between lines 37 and 48. This utility recursively imports all subpackages under a given namespace, which the CLI uses to build its service registry at runtime without hardcoding module paths.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →