# How Holehe Generates Random User Agents for OSINT Requests

> Learn how Holehe generates random user agents for OSINT requests by choosing from realistic Chrome signatures. Enhance your scraping with unique identifiers.

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

---

**Holehe generates random User-Agent headers by selecting from a static collection of realistic Chrome browser signatures stored in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py), using Python's `random.choice()` to vary the identifier for each outgoing HTTP request.**

Holehe, the popular email-based OSINT (Open Source Intelligence) tool, implements User-Agent rotation to prevent detection and blocking by target services during account enumeration checks. Rather than generating synthetic browser identifiers algorithmically, holehe relies on a curated local database of authentic Chrome User-Agent strings. This approach ensures that each HTTP request appears to originate from a different legitimate browser instance, significantly reducing the tool's fingerprint.

## User Agent Storage in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py)

Holehe maintains its collection of browser signatures in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py), which serves as a centralized repository for HTTP header spoofing. This file contains a JSON-structured dictionary named `ua` that groups User-Agent strings by browser type, currently featuring an extensive list of authentic Chrome signatures.

### The UA Dictionary Structure

The `ua` dictionary organizes strings hierarchically under browser categories. Accessing `ua["browsers"]["chrome"]` returns a list containing numerous realistic Chrome User-Agent strings collected from actual browser versions. This static approach eliminates external dependencies while ensuring the identifiers remain current and believable to web service defenses.

## Random Selection Implementation

Individual modules throughout the holehe codebase import this dictionary and utilize Python's built-in `random` module to select entries unpredictably for each request.

### The Selection Process

When preparing HTTP requests, modules execute a two-step process: first importing the `ua` dictionary from the local file, then applying `random.choice()` to select from the Chrome browser list. This implementation ensures that consecutive requests to the same target service carry different User-Agent headers, mimicking the behavior of disparate users.

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

# Select a random Chrome User-Agent string

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

```

## Practical Usage in Holehe Modules

The random User-Agent generation integrates directly into the request preparation logic found throughout `holehe/modules/`. Each module responsible for querying external services implements this pattern to maintain operational stealth.

### Basic Implementation Example

The following pattern demonstrates how holehe modules incorporate the random User-Agent selection into their HTTP request workflow:

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

def random_ua():
    """Return a random Chrome User-Agent string."""
    return random.choice(ua["browsers"]["chrome"])

# Use it when making a request

url = "https://example.com"
resp = requests.get(url, headers={"User-Agent": random_ua()})
print(resp.status_code)

```

### Module-Level Integration

Inside specific OSINT modules, such as those located in `holehe/modules/social_media/`, the implementation remains consistent. The module imports the `ua` dictionary, constructs headers with a randomly selected Chrome signature, and passes these headers to the HTTP client:

```python

# Inside a holehe module (simplified)

from holehe.localuseragent import ua
import random, requests

def check_account(email):
    headers = {"User-Agent": random.choice(ua["browsers"]["chrome"])}
    r = requests.post("https://service.com/api", data={"email": email}, headers=headers)
    return r.json()

```

This consistent implementation across the codebase ensures that every module benefits from the same level of request obfuscation without requiring redundant code or external API calls.

## Summary

- Holehe stores authentic browser signatures in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) within a dictionary named `ua`, specifically under `ua["browsers"]["chrome"]`.
- The tool uses `random.choice()` to select a different Chrome User-Agent string for each HTTP request, preventing pattern detection.
- Modules import the `ua` dictionary directly and apply the random selection during header construction.
- This static-list approach provides reliability and performance advantages over dynamic generation or external User-Agent services.

## Frequently Asked Questions

### Where does holehe store its User-Agent strings?

Holehe stores its collection of User-Agent strings in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py). This file contains a JSON-formatted dictionary named `ua` that organizes browser signatures by category, with an extensive list of Chrome User-Agent strings available under the `chrome` key.

### Which browser does holehe mimic with its User-Agent rotation?

According to the source code in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py), holehe currently focuses on Chrome browser signatures. The `ua["browsers"]["chrome"]` list contains numerous realistic Chrome User-Agent strings that the tool randomly selects from to mimic legitimate Chrome traffic.

### How does holehe select a specific User-Agent for each request?

Holehe uses Python's `random.choice()` function to select entries from the pre-loaded list. Each time a module prepares an HTTP request, it calls `random.choice(ua["browsers"]["chrome"])` to pick a different User-Agent string, ensuring variability between requests.

### Why does holehe use a static list instead of generating User-Agent strings dynamically?

The static list approach in [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) ensures that all User-Agent strings are authentic browser signatures that have been verified to work with target services. This method eliminates the risk of generating invalid or malformed identifiers that could trigger security filters, while also avoiding external dependencies that might compromise operational security or availability.