# How `localuseragent` Selects Realistic User Agents in holehe for Undetectable OSINT Requests

> Discover how holehe's localuseragent module selects realistic user agents for undetectable OSINT requests. Mimic genuine web traffic with curated browser strings.

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

---

**The `localuseragent` module in megadose/holehe maintains a curated JSON dictionary of realistic browser User-Agent strings that each OSINT module randomly samples to mimic genuine web traffic.**

The [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) file serves as the central repository for HTTP **User-Agent** headers across the entire holehe OSINT framework. Rather than hardcoding browser fingerprints in each module, holehe consolidates all UA strings into one location, enabling consistent, maintainable request polymorphism.

---

## What the `localuseragent` Module Contains

At the core of [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) is a single global variable **`ua`** defined on line 3. This variable stores a parsed JSON structure containing categorized browser signatures:

```python
ua = json.loads('''{
    "browsers": {
        "chrome": [ … list of Chrome UA strings … ],
        "firefox": [ … list of Firefox UA strings … ],
        "safari":  [ … list of Safari UA strings … ],
        "iOS":     [ … list of iOS UA strings … ]
    }
}''')

```

The dictionary organizes User-Agent strings by browser family, making it trivial to match the appropriate fingerprint to a target platform's expected traffic patterns.

---

## How User Agents Are Selected in holehe Modules

Each OSINT module imports the `ua` dictionary and selects a random entry at request time. This pattern appears consistently throughout the codebase.

### Import Patterns

Modules use one of two import styles:

```python
from holehe.localuseragent import ua

```

Or wildcard import:

```python
from holehe.localuseragent import *

```

### Random Selection Implementation

The selection mechanism relies on Python's `random.choice()` against the appropriate browser list:

```python
'User-Agent': random.choice(ua["browsers"]["chrome"])

```

This approach yields a non-deterministic, realistic browser fingerprint for every HTTP request.

---

## Real-World Usage in Core Modules

### Facebook Module ([`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py))

The Facebook checker demonstrates standard UA selection:

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

def check_facebook(email):
    headers = {
        'User-Agent': random.choice(ua["browsers"]["chrome"]),
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    }
    # perform request …

```

### Spotify Module ([`holehe/modules/music/spotify.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/music/spotify.py))

Spotify's module follows the same pattern:

```python
from holehe.localuseragent import ua

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

```

### Steam Module (Wildcard Import Example)

When using wildcard imports, the `ua` variable remains directly accessible:

```python
from holehe.localuseragent import *

def check_steam(email):
    headers = {
        'User-Agent': random.choice(ua["browsers"]["firefox"]),
    }
    # perform request …

```

---

## Why Randomized User-Agents Matter for OSINT

### Evasion of Bot Detection

Static User-Agent strings trigger fingerprinting defenses. By randomizing across plausible browser signatures, holehe requests appear as organic, human-driven traffic rather than automated scanning.

### Centralized Maintenance

All browser strings live in [`localuseragent.py`](https://github.com/megadose/holehe/blob/main/localuseragent.py). Updating Chrome versions, adding new Safari signatures, or pruning outdated Firefox UAs requires editing a single file. Changes propagate automatically to every module that imports `ua`.

### Platform-Appropriate Signatures

The categorized structure (`chrome`, `firefox`, `safari`, `iOS`) lets modules select contextually appropriate headers. A mobile-centric service might prefer `ua["browsers"]["iOS"]`, while enterprise platforms may expect desktop Chrome patterns.

---

## Key Files and Their Roles

| File | Purpose |
|------|---------|
| [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) | Master dictionary of categorized User-Agent strings exposed as `ua` |
| [`holehe/modules/social_media/facebook.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py) | Demonstrates `from holehe.localuseragent import ua` import and random selection |
| [`holehe/modules/music/spotify.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/music/spotify.py) | Uses `random.choice(ua["browsers"]["chrome"])` in production requests |
| [`holehe/modules/software/office365.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/software/office365.py) | Shows alternative pattern: passing UA via function argument (`user_agent`) |

---

## Summary

- **[`localuseragent.py`](https://github.com/megadose/holehe/blob/main/localuseragent.py)** stores all User-Agent strings as a parsed JSON dictionary in the global `ua` variable
- Modules import `ua` and call `random.choice()` to select non-deterministic, realistic browser fingerprints
- Four browser categories exist: `chrome`, `firefox`, `safari`, and `iOS`
- This architecture enables **polymorphic requests** that evade bot detection while remaining **centrally maintainable**

---

## Frequently Asked Questions

### Does holehe rotate User-Agents per request or per session?

Per request. The `random.choice()` call executes fresh for each HTTP request, meaning consecutive checks—even within the same module—may present different browser fingerprints. This maximizes entropy against rate-limiting systems.

### Can I add custom User-Agent strings to holehe?

Yes. Edit [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) and append strings to the appropriate browser list inside the JSON structure. All modules importing `ua` will immediately access your additions without code changes elsewhere.

### Why does holehe include iOS UAs separately from Safari?

Mobile Safari on iOS presents distinct headers from desktop Safari, including device identifiers and AppleWebKit versioning. The separate `iOS` category lets modules targeting mobile-first platforms (Instagram, Snapchat, etc.) select appropriate mobile fingerprints.

### What happens if [`localuseragent.py`](https://github.com/megadose/holehe/blob/main/localuseragent.py) fails to import?

The import failure would cascade to any module attempting `from holehe.localuseragent import ua`, causing an `ImportError` at module load time. The file has no external dependencies beyond Python's standard `json` library, making such failures rare.