How Holehe Implements User-Agent Rotation: A Deep Dive into the Source Code

Holehe rotates User-Agent strings by randomly selecting from a centralized JSON dictionary of browser fingerprints stored in holehe/localuseragent.py, then applying random.choice() on every HTTP request to mimic real browser traffic.

This email reconnaissance tool hides its automated nature by varying the User-Agent header for each service check it performs. Understanding how User-Agent rotation works in Holehe helps security researchers and developers implement similar evasion techniques in their own tools.

Central User-Agent Store in localuseragent.py

All supported browsers and their fingerprint strings are defined once in holehe/localuseragent.py. This file contains a JSON-encoded dictionary named ua where each key maps to a list of real-world User-Agent strings.

The structure organizes browsers under a browsers key:


# Simplified structure of holehe/localuseragent.py

ua = {
    "browsers": {
        "chrome": [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.0...",
            # ... dozens more Chrome variants

        ],
        "firefox": [
            "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101...",
            # ... Firefox variants

        ],
        "iOS": [
            "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X)...",
            # ... mobile Safari strings

        ],
        "safari": [
            # ... Safari desktop strings

        ]
    }
}

This centralized approach means updates—adding new UA strings or browser categories—propagate automatically to every module without code duplication.

Import Pattern Across Service Modules

Individual modules that interact with external services import this dictionary directly. The pattern appears consistently across Holehe's codebase:

from holehe.localuseragent import ua
import random

For example, in holehe/modules/social_media/facebook.py, the module imports ua at the top level, making the full collection available for all requests to Facebook's endpoints.

Random Selection Per Request

Before each request, Holehe builds a headers dictionary and fills the User-Agent entry with random.choice() from the appropriate browser list:

headers = {
    "User-Agent": random.choice(ua["browsers"]["chrome"]),
    "Accept": "application/json, text/plain, */*",
    "Origin": "https://www.facebook.com",
    "DNT": "1",
}

By calling random.choice every time a request executes, Holehe ensures consecutive calls use different UA strings. This pattern repeats across virtually every module—Instagram, Twitter, Reddit, Tumblr, Snapchat, and more.

Practical Code Examples

Selecting a Random Chrome User-Agent

from holehe.localuseragent import ua
import random

# Choose a Chrome UA each time the function runs

chrome_ua = random.choice(ua["browsers"]["chrome"])
print(chrome_ua)

Asynchronous Request with UA Rotation (Facebook Module)

import random
from holehe.localuseragent import ua

async def facebook(email, client, out):
    headers = {
        "User-Agent": random.choice(ua["browsers"]["chrome"]),
        "Accept": "application/json, text/plain, */*",
        "Accept-Encoding": "gzip, deflate",
        "Referer": "https://www.facebook.com/login/identify",
    }
    # Request logic continues...

Browser-Agnostic Rotation Function

def random_ua(browser: str = "chrome") -> str:
    """
    Return a random User-Agent string for the requested browser.
    Accepted values: 'chrome', 'firefox', 'iOS', 'safari', ...
    """
    return random.choice(ua["browsers"][browser])

# Example usage

headers = {"User-Agent": random_ua("firefox")}

Key Files Implementing User-Agent Rotation

File Role
holehe/localuseragent.py Central repository of browser-specific User-Agent strings (ua)
holehe/modules/social_media/facebook.py Demonstrates import of ua and random Chrome selection
holehe/modules/social_media/instagram.py Uses Chrome UA rotation for Instagram checks
holehe/modules/social_media/tumblr.py Shows rotation with the iOS UA list
holehe/modules/social_media/twitter.py Follows same pattern for Twitter/X requests
holehe/modules/social_media/snapchat.py Random UA selection for Snapchat endpoints
holehe/modules/transportation/blablacar.py Cross-domain reuse of the rotation pattern

Why This User-Agent Rotation Strategy Works

  • Variability: Real browsers send many different UA strings; rotating them mimics this natural variance across sessions and requests.
  • Simplicity: The single central list in localuseragent.py keeps maintenance trivial—one file update affects all modules.
  • Low overhead: random.choice operates in O(1) time, adding negligible latency to each HTTP request.

Summary

  • Holehe implements User-Agent rotation through a centralized dictionary in holehe/localuseragent.py
  • The ua variable contains browser-specific lists of realistic fingerprint strings
  • Every module imports ua and calls random.choice() before each request
  • This lightweight pattern appears consistently across social media, transportation, and other service modules
  • The O(1) selection performance ensures no meaningful slowdown in asynchronous operation

Frequently Asked Questions

How does Holehe avoid using the same User-Agent repeatedly?

Holehe calls random.choice() fresh for every HTTP request rather than caching a selection. This means even rapid sequential requests to the same service receive different UA strings, preventing fingerprinting based on static headers.

What browsers does Holehe's User-Agent rotation support?

According to the source in holehe/localuseragent.py, the ua dictionary includes chrome, firefox, iOS, and safari keys. Individual modules select the browser type most appropriate for their target service—Chrome for desktop sites, iOS for mobile-heavy platforms.

Can I add custom User-Agent strings to Holehe?

Yes. Since holehe/localuseragent.py uses a plain Python dictionary structure, you can append strings to any browser list. New entries automatically become available to all modules that import ua without requiring code changes elsewhere.

Does User-Agent rotation completely prevent blocking?

No single technique guarantees evasion. However, as implemented in megadose/holehe, User-Agent rotation combines with other request randomization (headers, timing) to reduce bot detection probability. The source code shows this is one layer in a broader operational security strategy.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →