How Holehe Modules Are Organized by Category: A Technical Guide

Holehe groups all service-specific checks into the holehe.modules package, where each sub-directory represents a distinct category (social media, shopping, programming, etc.) and every Python file implements a check for a specific platform.

Understanding how Holehe modules are organized by category is essential for contributing to the megadose/holehe repository or extending its reconnaissance capabilities. The project uses a clean hierarchical structure that separates services by domain, allowing the core loader to dynamically discover and execute checks without manual registration.

The holehe.modules Package Structure

The repository stores every service check inside the holehe/modules/ directory. Each immediate sub-directory represents a category (or domain), while individual .py files within those folders implement concrete platform checks.

For example, the path holehe/modules/social_media/twitter.py indicates:

  • Category: social_media
  • Service: twitter

The current categories reflected in the source tree include:

Each category folder contains an intentionally empty __init__.py. The loader does not require explicit imports; it discovers modules by traversing the directory tree.

How the Core Loader Discovers Categories

In holehe/core.py, the import_submodules function walks the package tree using pkgutil.walk_packages to import every file dynamically:

modules = import_submodules("holehe.modules")
websites = get_functions(modules, args)

The import_submodules utility preserves the hierarchical path, importing modules as fully-qualified names like holehe.modules.social_media.twitter. Subsequently, get_functions extracts callable objects whose fully-qualified names contain more than three parts, converting each service file into an asynchronous function ready for execution.

This design means no registration is required when adding new services. Placing a new .py file in the appropriate category folder automatically includes it in the next run.

Programmatically Listing Modules by Category

You can inspect the categorical organization at runtime using the same utilities the core employs:

from holehe.core import import_submodules, get_functions

# Load every submodule under holehe.modules

all_modules = import_submodules("holehe.modules")

# Retrieve the callable check functions

functions = get_functions(all_modules)

# Print the category and module name

for fn in functions:
    print(f"Category: {fn.__module__}")  # e.g., holehe.modules.social_media.twitter

    print(f"Function: {fn.__name__}")    # e.g., twitter

The output reveals the module structure, showing which services belong to which categories based on their import paths.

Running Individual Category Checks

To execute a specific check from a category manually, import the function directly from its category path and run it asynchronously:

import httpx
import trio
from holehe.modules.social_media.twitter import twitter

async def run_check(email):
    async with httpx.AsyncClient() as client:
        out = []
        await twitter(email, client, out)
        print(out)

# Execute the check

trio.run(run_check, "example@example.com")

This pattern works for any service, whether from holehe.modules.shopping.amazon or holehe.modules.programing.github.

Extending Categories with New Services

Adding coverage for a new platform requires only two steps:

  1. Identify the appropriate category folder (or create a new one if the domain is unique)
  2. Place a Python file implementing the async check function into that folder

The core loader in holehe/core.py will automatically detect the new file on the next execution, preserving the categorical organization without modifying the main program logic.

Summary

  • Holehe modules are organized by category through sub-directories under holehe/modules/, where folder names represent service domains (social_media, shopping, programing, etc.)
  • Dynamic loading occurs via import_submodules in holehe/core.py, which walks the package tree and imports every module without explicit registration
  • Individual checks reside as Python files within category folders (e.g., holehe/modules/social_media/twitter.py)
  • Empty __init__.py files mark directories as Python packages while allowing the loader to discover contents automatically
  • Extensibility is built-in: adding a new service requires only placing a file in the correct category directory

Frequently Asked Questions

How does Holehe load modules from different categories?

Holehe uses pkgutil.walk_packages in the import_submodules function (located in holehe/core.py) to recursively discover all Python files under holehe/modules/. It imports each file while preserving the hierarchical path structure, then get_functions extracts the callable check objects. This dynamic approach eliminates the need for a central registry or manual imports when new categories or services are added.

Where are the social media checks located in Holehe?

Social media checks reside in the holehe/modules/social_media/ directory. Specific implementations include twitter.py, instagram.py, and facebook.py. Each file contains an async function matching the filename (e.g., async def twitter(...)), which the core loader executes when checking for account existence on those platforms.

Can I add my own custom category to Holehe?

Yes. Create a new sub-directory under holehe/modules/ with the desired category name (e.g., holehe/modules/crypto/), include an empty __init__.py file, and place your service check files inside. The next time Holehe runs, import_submodules will automatically detect the new category and load any Python files it contains, making them available for execution alongside existing categories.

Why are the __init__.py files empty in category folders?

The empty __init__.py files serve only as package markers to designate directories as Python packages, enabling pkgutil.walk_packages to traverse them. Since holehe/core.py discovers modules by walking the filesystem rather than importing specific names, no initialization code or explicit imports are required in these files. This keeps the category structure clean and minimizes maintenance when adding or removing services.

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 →