# How Holehe Handles User Agents and Avoids Detection

> Discover how Holehe expertly handles user agents, rotating realistic browser headers to evade detection. Learn about its centralized dictionary and per-module random selection strategy.

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

---

**Holehe mitigates detection by rotating realistic browser `User-Agent` headers on every HTTP request through a centralized JSON dictionary and per-module random selection.**

Holehe is an open-source email OSINT (Open Source Intelligence) framework by megadose designed to enumerate account registrations across hundreds of online services. To avoid triggering rate limits or bot detection mechanisms during bulk scanning operations, the tool implements a dynamic user agent management system. This analysis examines how Holehe handles user agents and avoids detection through its distributed header injection architecture.

## Centralized User-Agent Store

### The localuseragent.py Module

The foundation of Holehe's evasion strategy resides in **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)**, which defines a JSON-encoded dictionary named `ua`. This structure contains realistic browser strings for Chrome, Firefox, Safari, and iOS platforms that mimic genuine user traffic. The module loads these strings at runtime using `json.loads()`, making them available as a shared resource across the entire codebase.

The `ua` dictionary is organized by browser categories, allowing modules to select context-appropriate signatures depending on the target service's expected audience.

## Per-Request Randomization Strategy

Individual service modules import the `ua` dictionary and invoke **`random.choice()`** to select a new user agent for every distinct HTTP request. For example, in **[`holehe/modules/transport/blablacar.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/transport/blablacar.py)**, the request headers are constructed as follows:

```python
from holehe.localuseragent import ua
import random

headers = {'User-Agent': random.choice(ua["browsers"]["firefox"])}

```

This pattern appears in over 100 locations throughout the **`holehe/modules/`** directory, ensuring no two consecutive requests share the same browser fingerprint. By distributing the selection logic across individual modules rather than using a central interceptor, Holehe ensures that even parallel requests to different services carry unique signatures.

## Privacy-Enhancing Headers

Beyond user agent rotation, certain modules append additional privacy signals to mimic legitimate browser behavior. The **DNT: 1** (Do Not Track) header appears in medical and privacy-sensitive modules such as Sevencups, signaling settings consistent with genuine privacy-conscious users. These supplementary headers complement the user agent rotation by presenting a holistic browser profile that matches expected human traffic patterns.

## HTTP Client Architecture

### Shared AsyncClient with Variable Headers

Holehe leverages **`httpx.AsyncClient`** for asynchronous HTTP requests, instantiated centrally in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)**. While the client instance persists across requests to optimize connection pooling and TCP reuse, each module generates a fresh `headers` dictionary containing a randomly selected user agent before calling the client.

This architecture balances performance with evasion: the underlying TCP connection remains stable to reduce latency, while each HTTP request carries distinct headers that prevent pattern recognition by web application firewalls.

## Practical Implementation Example

The following pattern demonstrates how Holehe modules combine these techniques in practice:

```python
from holehe.localuseragent import ua
import random
import httpx

async def check_service(email: str, client: httpx.AsyncClient):
    # Randomize user agent for this specific request

    headers = {
        "User-Agent": random.choice(ua["browsers"]["chrome"]),
        "DNT": "1"  # Privacy signal

    }
    
    # Shared client ensures connection reuse

    response = await client.get(
        "https://target-service.com/api/check",
        headers=headers
    )
    return response.json()

```

This implementation ensures that the shared `httpx.AsyncClient` maintains persistent connections while each request presents a unique browser identity.

## Summary

- **Centralized storage**: Realistic browser strings are maintained in **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)** as a JSON dictionary loaded at runtime.
- **Randomized selection**: Over 100 modules use **`random.choice(ua["browsers"][...])`** to inject a unique `User-Agent` header per request.
- **Client efficiency**: A shared **`httpx.AsyncClient`** in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)** persists connections while headers vary per request.
- **Additional obfuscation**: Optional **DNT: 1** headers in certain modules mimic privacy-conscious user behavior.

## Frequently Asked Questions

### How does Holehe select user agents for each request?

Holehe modules import the `ua` dictionary from **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)** and call `random.choice()` on browser-specific sublists (e.g., `ua["browsers"]["firefox"]`) to select a string immediately before making an HTTP request.

### Does Holehe reuse the same user agent across multiple sites?

No. Because each of the 100+ modules independently selects a random user agent when constructing request headers, consecutive requests to different services carry distinct browser signatures.

### What additional headers does Holehe use to avoid detection?

Certain modules include the **DNT: 1** header to signal "Do Not Track" preferences, aligning the request profile with privacy-conscious human users and reducing bot detection risk.

### Where does Holehe store its list of user agents?

The user agent strings are stored as a JSON-encoded dictionary in **[`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)**, which is imported and accessed by service modules across the **`holehe/modules/`** directory tree.