How holehe Handles User Agents: Built-in Rotation and Randomization
holehe ships with a static collection of realistic browser User-Agent strings stored in holehe/localuseragent.py and rotates them randomly on every request to mimic legitimate browser traffic and avoid bot detection.
holehe is an open-source OSINT tool that probes external services to uncover account associations linked to email addresses. To evade simple bot detection mechanisms employed by the platforms it queries, the tool implements a User-Agent rotation system that cycles through authentic browser signatures defined directly in the source code.
Where User Agents Are Defined in holehe
The complete list of browser signatures lives in holehe/localuseragent.py. This file contains a JSON literal named ua that acts as a static database of client headers.
# holehe/localuseragent.py (conceptual structure)
ua = {
"browsers": {
"chrome": [
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36...",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
# ... additional Chrome variants
]
}
}
The ua dictionary organizes strings by browser family, allowing the tool to select from specific vendor fingerprints (primarily Chrome) when constructing HTTP headers.
How holehe Rotates User Agents
Rather than using a single static string that triggers rate-limiting, holehe implements randomized selection at the request level. In both holehe/core.py and holehe/instruments.py, the code imports the ua dictionary and applies random.choice() to select an entry for each outgoing connection.
from .localuseragent import ua
import random
headers = {
"User-Agent": random.choice(ua["browsers"]["chrome"]),
# Additional headers...
}
This approach ensures that consecutive requests to the same service present different client signatures, reducing the probability of fingerprint-based blocking.
Implementation in HTTP Requests
When holehe initiates a probe against a target service, it assembles a header dictionary that includes the randomly selected User-Agent string. The following simplified example demonstrates the pattern used throughout the codebase:
import requests
from holehe.localuseragent import ua
import random
def probe_service(email, service_endpoint):
headers = {
"User-Agent": random.choice(ua["browsers"]["chrome"]),
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate"
}
response = requests.get(
service_endpoint,
headers=headers,
timeout=10
)
return response
The tool consistently applies this pattern across all modules, including the core orchestration logic in holehe/core.py and the helper utilities in holehe/instruments.py, ensuring uniform header distribution across the entire attack surface.
Benefits of User-Agent Rotation in OSINT
Rotating User-Agent strings provides multiple operational advantages for reconnaissance tools:
- Evasion of trivial bot filters that blacklist generic or missing client headers.
- Mimicry of legitimate browser traffic by presenting current Chrome signatures with realistic platform tokens.
- Distributed request fingerprinting that prevents services from correlating multiple probes based on a static client signature.
This technique is critical for holehe's effectiveness, as the tool must query dozens of external platforms without triggering automated defensive measures.
Summary
- Storage Location: User-Agent strings are stored as a JSON literal (
ua) inholehe/localuseragent.py. - Selection Method: The tool uses
random.choice()to pick entries fromua["browsers"]["chrome"]. - Application Scope: Headers are constructed in
holehe/core.pyandholehe/instruments.pybefore every HTTP request. - Operational Goal: Randomization prevents bot detection and improves probe success rates against external services.
Frequently Asked Questions
Can I add custom User-Agent strings to holehe?
Yes. You can modify the ua dictionary in holehe/localuseragent.py to include additional browser signatures or platform variants. Simply append new strings to the ua["browsers"]["chrome"] list (or add new browser categories) and restart the tool. The random.choice() implementation will automatically include your additions in the rotation pool.
Which browsers does holehe simulate?
According to the current source code, holehe primarily distributes Chrome User-Agent strings via ua["browsers"]["chrome"]. The bundled signatures represent various Windows and desktop Chrome versions to maximize compatibility with modern web services that expect Chromium-based headers.
Is the User-Agent rotated per request or per session?
The User-Agent is rotated per request. Each time holehe builds an HTTP request (as seen in holehe/instruments.py), it calls random.choice() fresh, meaning consecutive requests to the same or different services may present different signatures. This maximizes entropy compared to session-based rotation.
Does User-Agent rotation guarantee holehe won't be blocked?
No. While rotating User-Agents prevents trivial signature-based blocking, sophisticated anti-bot systems analyze behavioral patterns, IP reputation, TLS fingerprints, and JavaScript execution. The User-Agent management in holehe handles the first layer of defense but should be combined with other operational security measures for high-sensitivity probes.
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 →