Does Holehe Support Custom User Agents? A Deep Dive into the Source Code

Holehe does not support custom User-Agent strings through any public API, command-line option, or configuration file—it randomly selects from a hard-coded browser list defined in holehe/localuseragent.py.

The open-source OSINT tool holehe (maintained by megadose) is designed to check if an email address is registered across hundreds of websites. Understanding its User-Agent handling is crucial for users who need to customize request fingerprinting or avoid detection. This article examines the actual implementation in the megadose/holehe repository to explain exactly how User-Agents work—and why you cannot easily change them.

How Holehe Handles User-Agent Strings Internally

The Central User-Agent Source

All HTTP requests in holehe pull from a single source: the localuseragent module. The file holehe/localuseragent.py contains a hard-coded dictionary ua with browser-specific lists:


# Simplified structure from holehe/localuseragent.py

ua = {
    "browsers": {
        "chrome": [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...",
            # ... dozens more Chrome UAs

        ],
        "firefox": [...],
        "safari": [...]
    }
}

Random Selection in Request Modules

Individual site-checking modules import this dictionary and use random.choice() to pick a User-Agent for each request. For example, in holehe/modules/social_media/facebook.py:

import random
from holehe.localuseragent import ua

# Inside the check() function

headers = {
    'User-Agent': random.choice(ua["browsers"]["chrome"]),
    'Accept': 'text/html,...',
    # ...

}

This pattern repeats across the codebase. The holehe/modules/transport/blablacar.py file and dozens of other modules follow identical implementation—no module accepts an external User-Agent parameter.

Why You Cannot Pass a Custom User-Agent

No CLI Option in Core Entry Point

The main entry point at holehe/core.py defines the command-line interface. Analysis of this file confirms no --user-agent or similar argument exists. The argparse configuration only exposes:

  • Target email address
  • Output modules
  • Rate limiting options
  • Timeout settings

No Function Parameter Exposure

The check() functions across all modules use a consistent signature:

async def check(email: str, client: AsyncClient, out: ...) -> None:
    # No user_agent parameter available

The client parameter is an httpx.AsyncClient instance, but holehe initializes this internally without exposing headers for customization.

Workaround: Modifying Source Code for Custom User-Agents

Since no official API exists, users requiring custom User-Agents must edit the source directly. Two approaches work:

Option 1: Replace the Random Choice (Module-Specific)

Edit the specific module you want to modify:


# In holehe/modules/social_media/facebook.py

# Replace this line:

# 'User-Agent': random.choice(ua["browsers"]["chrome"]),

# With a fixed custom string:

CUSTOM_UA = "MyApp/1.0 (+https://example.com)"
headers = {'User-Agent': CUSTOM_UA, ...}

Option 2: Monkey-Patch the ua Dictionary (Global Change)

For a project-wide modification without editing multiple files:

import holehe.localuseragent
holehe.localuseragent.ua["browsers"]["chrome"] = [
    "MyCustomAgent/1.0 (Research Project)"
]

# Then run holehe normally

from holehe.core import main
main()

Warning: Both approaches require maintaining a fork or local patch, as upgrades to holehe will overwrite changes.

Comparing User-Agent Handling to Similar Tools

Tool Custom User-Agent Support Implementation
Holehe ❌ Not supported Hard-coded random selection from localuseragent.py
Sherlock ✅ Supported via --user-agent flag CLI argument passed to requests
WhatBreach ❌ Not supported Static User-Agent string
GHunt ⚠️ Partial Uses Google OAuth; limited header control

Holehe's random rotation approach provides basic evasion against simple fingerprinting, but lacks flexibility for users with specific compliance or operational requirements.

Summary

  • Holehe does not support custom User-Agents through any configuration, CLI option, or function parameter.
  • All modules import localuseragent and use random.choice(ua["browsers"]["chrome"]) (or similar) to select headers.
  • Modification requires source code changes: either edit holehe/localuseragent.py directly or monkey-patch the ua dictionary before importing modules.
  • Key files: holehe/localuseragent.py (UA definitions), holehe/modules/*/*.py (usage sites), holehe/core.py (CLI entry point).

Frequently Asked Questions

Can I set a custom User-Agent with a holehe command-line flag?

No. The holehe/core.py file contains no --user-agent or related argument in its argparse configuration. The CLI only accepts email targets, output modules, and connection settings like timeout and rate limit.

Where does holehe get its User-Agent strings from?

The holehe/localuseragent.py file contains a hard-coded ua dictionary with categorized browser strings. Modules import this dictionary and randomly select from ua["browsers"]["chrome"], ua["browsers"]["firefox"], or other subcategories depending on the target site's expected browser profile.

Will holehe add official User-Agent customization in future versions?

Based on the current architecture across megadose/holehe, this would require significant refactoring. Every module's check() function would need signature changes, and core.py would need new CLI arguments. No open issues or pull requests suggest this feature is planned as of the latest repository analysis.

Is rotating random User-Agents better than a fixed custom one?

For OPSEC purposes: yes. Holehe's random rotation helps avoid trivial fingerprinting by services tracking single-User-Agent patterns. However, for users requiring whitelisted or identifiable User-Agents (corporate environments, bug bounty programs with disclosure requirements), the lack of customization is a limitation that requires source modification.

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 →