How `get_functions` Filters Holehe Modules Based on Command-Line Arguments

The get_functions helper in holehe filters modules by checking the args.nopasswordrecovery flag and excluding four specific sites—adobe, mail_ru, odnoklassniki, and samsung—when the --no-password-recovery option is enabled.

Holehe is an open-source OSINT tool developed by megadose that checks email addresses against hundreds of websites to uncover registered accounts. The tool dynamically discovers site-checking modules and selectively filters them based on runtime flags. Understanding how get_functions performs this filtering reveals important details about holehe's modular architecture and execution pipeline.

Where get_functions Lives in the Codebase

The filtering logic resides in holehe/core.py, which serves as the main entry point for the entire application. This file handles argument parsing, module discovery, and the async orchestration of site checks.

The relevant function spans lines 50-63:

def get_functions(modules, args=None):
    """Transform the modules objects to functions"""
    websites = []

    for module in modules:
        # Only consider real site modules (depth > 3)

        if len(module.split(".")) > 3:
            modu = modules[module]                # the imported module object

            site = module.split(".")[-1]          # e.g. "github", "adobe", …

            
            # ── Filtering based on the "‑NP / --no‑password‑recovery" flag ──

            if args is not None and args.nopasswordrecovery == True:
                # Exclude sites that expose password‑recovery helpers

                # (adobe, mail_ru, odnoklassniki, samsung)

                if ("adobe"      not in str(modu.__dict__[site]) and
                    "mail_ru"    not in str(modu.__dict__[site]) and
                    "odnoklassniki" not in str(modu.__dict__[site]) and
                    "samsung"    not in str(modu.__dict__[site])):
                    websites.append(modu.__dict__[site])
            else:
                # No filtering – keep every discovered site function

                websites.append(modu.__dict__[site])
    return websites

The function receives two parameters:

  • modules — a dictionary of imported submodule objects from holehe/modules
  • args — the parsed ArgumentParser namespace (optional, defaults to None)

The Module Discovery Pipeline

Before get_functions can filter anything, holehe must first discover available modules. This happens through a separate helper called import_submodules.

The execution flow proceeds as follows:

  1. import_submodules("holehe.modules") recursively imports every Python file under holehe/modules/ and returns a dictionary mapping module names to module objects
  2. get_functions(modules, args) transforms these module objects into executable site-checking functions, applying filters based on command-line arguments
  3. The resulting websites list is passed to the async nursery (launch_module) for parallel execution against the target email address

How the --no-password-recovery Filter Works

The critical filtering logic activates when users pass -NP or --no-password-recovery. This flag gets parsed in holehe/core.py at lines 90-92:

parser.add_argument("-NP", "--no-password-recovery", action='store_true', default=False,
                    help="Don't try password recovery on each website")

When present, args.nopasswordrecovery becomes True. Inside get_functions, this triggers a substring-based exclusion check against four hardcoded site names:

Excluded Site Rationale
adobe Password recovery involves additional API calls
mail_ru Russian mail service with recovery-specific endpoints
odnoklassniki Social network requiring recovery flow interactions
samsung Account recovery triggers extended verification steps

The check works by converting the site function object to its string representation and verifying none of these substrings appear:

"adobe" not in str(modu.__dict__[site])

This approach relies on the fact that Python function objects include their module path in __repr__, making the site name detectable without explicit metadata.

Practical Usage Examples

Run holehe with full password recovery attempts (default behavior):

holehe user@example.com

Skip password-recovery modules for faster, lighter scanning:


# Short form

holehe user@example.com -NP

# Long form

holehe user@example.com --no-password-recovery

In the first case, all discovered modules execute including the four password-recovery sites. In the second case, get_functions reduces the workload by excluding those specific modules, resulting in fewer HTTP requests and reduced execution time.

Key Design Decisions

The filtering implementation reflects several practical engineering choices:

  • Namespace depth check — The len(module.split(".")) > 3 guard ensures only actual site modules are processed, skipping package-level __init__.py files
  • String-based matching — Rather than maintaining a registry of module classes or decorators, holehe uses simple substring detection against function representations
  • Explicit opt-out — Password recovery is included by default since it can yield valuable account existence confirmations, but users can disable it when speed or stealth matters

These choices keep the codebase lightweight while providing meaningful control over execution scope.

File Purpose
holehe/core.py Main entry point; argument parsing, get_functions definition, async orchestration
holehe/modules/__init__.py Package marker for site-specific checking modules
holehe/instruments.py Progress bar instrumentation for async task monitoring

Summary

  • get_functions in holehe/core.py transforms imported module objects into executable site-checking functions
  • When args.nopasswordrecovery is True, the function excludes adobe, mail_ru, odnoklassniki, and samsung by checking their string representations
  • The --no-password-recovery flag (or -NP) triggers this filtering to reduce API calls and execution time
  • Module discovery relies on import_submodules, while execution uses async nursery pattern via launch_module

Frequently Asked Questions

How does holehe know which modules support password recovery?

Holehe uses hardcoded site names in get_functions rather than detecting capabilities dynamically. The four excluded sites—adobe, mail_ru, odnoklassniki, and samsung—are explicitly listed in the filtering logic based on known recovery-flow implementations in their respective modules.

Can I exclude other sites besides the password-recovery ones?

Not through built-in flags. The current implementation only supports filtering those four specific sites via --no-password-recovery. To exclude additional sites, you would need to modify the get_functions implementation in holehe/core.py or fork the repository.

Why check str(modu.__dict__[site]) instead of using a module attribute?

The string-based approach avoids requiring every module to implement a specific interface or metadata attribute. Since Python function objects naturally include their defining module in the string representation, this lightweight detection works without additional boilerplate across all 120+ site modules.

What happens if args is None when calling get_functions?

The function handles None gracefully by skipping the password-recovery filter and appending all discovered site modules. This ensures backward compatibility for any internal callers that don't pass an argument namespace.

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 →