Developer Guide: Creating a New Module

Holehe is designed to be easily extensible. If you want to add support for a new website, you can create a new module file.

Module Structure

A module is a Python file (e.g., mysite.py) located in the appropriate subdirectory of holehe/modules/. It must contain an asynchronous function with a specific signature.

Function Signature

from holehe.core import *
from holehe.localuseragent import *

async def mysite(email, client, out):
    name = "mysite"
    domain = "mysite.com"
    method = "register"  # register, login, password recovery, or other
    frequent_rate_limit = False

    # ... Logic goes here ...

Inputs

  1. email (str): The target email address to check.
  2. client (httpx.AsyncClient): The HTTP client provided by the core logic. Use this to make requests.
  3. out (list): A list where you append the result dictionary.

Logic Guidelines

  1. User Agents: Use random.choice(ua["browsers"]["chrome"]) (or firefox/safari) from holehe.localuseragent to randomize headers.
  2. Requests: Use await client.get(...) or await client.post(...).
  3. Error Handling: Wrap requests in try/except blocks to handle connection errors gracefully. If an exception occurs, append a result with "error": True.
  4. Verification: Check the response status code, JSON content, or HTML text to determine if the email is in use.

Output Format

You must append a dictionary to the out list. Do not return values.

out.append({
    "name": name,
    "domain": domain,
    "method": method,
    "frequent_rate_limit": frequent_rate_limit,
    "rateLimit": False,          # True if rate limited
    "exists": True,              # True if account found
    "emailrecovery": None,       # String if found (e.g. "a*****@gmail.com")
    "phoneNumber": None,         # String if found
    "others": None               # Dict or String for extra info
})

Example Template

from holehe.core import *
from holehe.localuseragent import *

async def example_site(email, client, out):
    name = "examplesite"
    domain = "examplesite.com"
    method = "register"
    frequent_rate_limit = False

    headers = {
        'User-Agent': random.choice(ua["browsers"]["chrome"])
    }

    try:
        # Example: Checking a registration API
        req = await client.get(f"https://api.examplesite.com/check/{email}", headers=headers)

        if req.status_code == 200 and "already_registered" in req.text:
            exists = True
        else:
            exists = False

        out.append({
            "name": name,
            "domain": domain,
            "method": method,
            "frequent_rate_limit": frequent_rate_limit,
            "rateLimit": False,
            "exists": exists,
            "emailrecovery": None,
            "phoneNumber": None,
            "others": None
        })

    except Exception:
        # Handle connection errors/timeouts
        out.append({
            "name": name,
            "domain": domain,
            "method": method,
            "frequent_rate_limit": frequent_rate_limit,
            "rateLimit": True,
            "exists": False,
            "emailrecovery": None,
            "phoneNumber": None,
            "others": None
        })