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
localuseragentand userandom.choice(ua["browsers"]["chrome"])(or similar) to select headers. - Modification requires source code changes: either edit
holehe/localuseragent.pydirectly or monkey-patch theuadictionary 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →