How to Add a Custom Module to Holehe: Complete Developer Guide

To add a custom module to Holehe, create a Python file implementing a class with a NAME attribute and a run(self, email) method that returns a status dictionary, place it in the appropriate holehe/modules/ subdirectory, and register it by importing the class in that sub-package's __init__.py.

Holehe is an open-source email reconnaissance framework that checks whether an address is registered across hundreds of online services. Adding a custom module to Holehe allows you to extend its coverage to new platforms by conforming to its standardized plugin architecture, which the core engine in holehe/core.py uses to automatically discover and execute service checks.

Understanding the Holehe Module Architecture

Module Location and Structure

All service modules reside within the holehe/modules/ directory, organized into sub-packages by service category. The repository includes folders such as social_media/, shopping/, and crm/, each containing individual Python files representing specific platforms. When you add a custom module to Holehe, you must place the file in the appropriate category folder or create a new sub-package if the service defines a new vertical.

The Standard Interface

Every module must implement a consistent interface so that holehe/core.py can execute it generically. The required contract includes:

  • A class-level NAME attribute (string) that identifies the service in output reports
  • A run(self, email) method that accepts an email string and returns a dictionary containing:
    • "status": Boolean indicating whether the account exists (True) or not (False)
    • "message": Human-readable string describing the result or error

Automatic Discovery Mechanism

The framework uses holehe/modules/__init__.py to walk through sub-packages and import all module classes into an internal registry. When a user runs holehe -l <email>, the core engine iterates this registry and invokes each module's run() method asynchronously, aggregating results into the final report.

Step-by-Step Guide to Adding a Custom Module

  1. Select the category – Choose the appropriate sub-package under holehe/modules/ (e.g., social_media/). Create a new folder with an __init__.py if the category does not exist.

  2. Create the module file – Add a new Python file within the chosen directory, such as holehe/modules/social_media/myservice.py.

  3. Implement the interface – Define a class with the NAME attribute and run(self, email) method returning the required dictionary format.

  4. Register the class – Edit the __init__.py in the same directory to import your class: from .myservice import MyService.

  5. Verify integration – Run holehe -l test@example.com and confirm your module appears in the output and executes correctly.

Custom Module Implementation Example

The following example follows the same pattern as the built-in Facebook module. Save this as holehe/modules/social_media/custom_platform.py:

import requests
from holehe.modules.base import BaseModule  # Optional inheritance for shared utilities

class CustomPlatform(BaseModule):
    """
    Check email registration status on CustomPlatform.
    """
    NAME = "CustomPlatform"

    def run(self, email: str) -> dict:
        """
        Query CustomPlatform API to verify if email is registered.

        Parameters
        ----------
        email : str
            The email address to verify.

        Returns
        -------
        dict
            Dictionary with keys:
            - status (bool): True if account exists, False otherwise
            - message (str): Description of result or error
        """
        try:
            response = requests.get(
                f"https://api.customplatform.com/v1/users/check?email={email}",
                timeout=10,
                headers={"User-Agent": "Holehe/1.0"}
            )
            
            if response.status_code == 200:
                data = response.json()
                exists = data.get("user_exists", False)
                return {
                    "status": exists,
                    "message": "Account found" if exists else "No account"
                }
            elif response.status_code == 404:
                return {"status": False, "message": "Account not found"}
            else:
                return {
                    "status": False,
                    "message": f"Unexpected HTTP {response.status_code}"
                }
        except requests.RequestException as exc:
            return {"status": False, "message": f"Network error: {str(exc)}"}

Registering Your Module

After creating the file, you must expose the class to the discovery mechanism. Modify holehe/modules/social_media/__init__.py to include your import:


# holehe/modules/social_media/__init__.py

from .facebook import Facebook
from .instagram import Instagram
from .custom_platform import CustomPlatform  # Add this line

The top-level holehe/modules/__init__.py automatically imports all sub-packages, so no additional changes are required at the root level if you placed your module within an existing category.

Testing Your Implementation

Execute Holehe with a verbose flag to verify your module loads and runs:

holehe -l test@example.com

Look for your NAME value in the output table. If the module fails to appear:

  • Confirm the file resides in holehe/modules/<category>/
  • Verify the class name matches the import statement in __init__.py
  • Ensure run() returns the exact dictionary structure with status and message keys
  • Check that NAME is defined as a class attribute, not an instance attribute

Summary

  • Location: Place custom modules in holehe/modules/ subdirectories (e.g., social_media/, shopping/)
  • Interface: Implement a class with NAME attribute and run(self, email) returning {"status": bool, "message": str}
  • Registration: Import the class in the sub-package's __init__.py to enable automatic discovery
  • Core Integration: holehe/core.py builds the execution registry from holehe/modules/__init__.py and invokes each module's run() method during scans
  • Error Handling: Modules should catch exceptions and return status: False with descriptive messages rather than raising errors

Frequently Asked Questions

Where should I place my custom module in the Holehe repository?

Place your Python file in the appropriate category folder under holehe/modules/, such as holehe/modules/social_media/ for social platforms. If the service category does not exist, create a new directory with an empty __init__.py file to make it a proper Python package, then place your module inside.

What methods and attributes are required in a Holehe custom module class?

Your class must define a NAME class attribute (a string identifier used in reports) and a run(self, email) method that accepts an email string parameter and returns a dictionary containing "status" (a boolean indicating account existence) and "message" (a human-readable result string). These specific names and types are required for the core engine in holehe/core.py to process your results correctly.

How does Holehe discover modules automatically without manual registry updates?

The holehe/modules/__init__.py script walks through all sub-packages during initialization. Each sub-package's __init__.py (such as holehe/modules/social_media/__init__.py) imports its module classes explicitly. When you add an import statement there, the top-level loader registers the class, making it available to the execution loop in holehe/core.py without modifying the core code itself.

Can I distribute a Holehe module as a standalone package without modifying the core repository?

Currently, Holehe requires modules to be integrated directly into the holehe/modules/ directory structure and registered via the sub-package __init__.py files. The framework does not support external plugin directories or entry-point-based discovery; to add a custom module to Holehe, you must place files within the source tree and ensure they are imported by the existing package initialization system.

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 →