# How holehe Handles User Agents: Built-in Rotation and Randomization

> Discover how holehe handles user agents by rotating realistic browser strings randomly on each request to bypass bot detection and mimic real user traffic.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: internals
- Published: 2026-08-22

---

**holehe ships with a static collection of realistic browser User-Agent strings stored in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)**. This file contains a JSON literal named **`ua`** that acts as a static database of client headers.

```python

# 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`](https://github.com/megadose/holehe/blob/main/holehe/core.py) and [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py), the code imports the `ua` dictionary and applies `random.choice()` to select an entry for each outgoing connection.

```python
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:

```python
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`](https://github.com/megadose/holehe/blob/main/holehe/core.py) and the helper utilities in [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/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`) in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py).
- **Selection Method:** The tool uses `random.choice()` to pick entries from `ua["browsers"]["chrome"]`.
- **Application Scope:** Headers are constructed in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) and [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) before 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`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/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.