How HTTP Clients Are Configured and Managed in Holehe Modules

Holehe centralizes HTTP client configuration in holehe/core.py by instantiating a single shared httpx.AsyncClient that is injected into every module function, enabling connection pooling, TLS session reuse, and consistent timeout handling across all OSINT requests.

The open-source OSINT tool Holehe relies on asynchronous HTTP requests to check email registration statuses across hundreds of platforms. Understanding how HTTP clients are configured and managed in Holehe modules is essential for developers extending the tool or debugging network behavior. The architecture follows a dependency injection pattern where a single client instance is created at startup and reused throughout the execution lifecycle.

Centralized Client Initialization in core.py

Inside holehe/core.py, the maincore() function constructs the HTTP client when the CLI initializes. It creates an httpx.AsyncClient with a user-configurable timeout value derived from the --timeout argument.


# holehe/core.py – client construction

client = httpx.AsyncClient(timeout=timeout)          # ← single client

...
async def launch_module(module, email, client, out):
    await module(email, client, out)                 # ← passed to each module

The launch_module Helper

The launch_module helper serves as the bridge between core orchestration logic and individual site modules. It accepts the module function, target email, the shared client instance, and an output list, then invokes the module as an async coroutine. This ensures every module receives the same configured client without instantiating new connection pools.

Module-Level Implementation Pattern

Every module in the holehe/modules/ directory follows a consistent async signature: async def module_name(email, client, out). The client parameter receives the shared httpx.AsyncClient instance, allowing modules to execute HTTP requests without managing connection state or SSL contexts.

Example: facebook.py Implementation

The Facebook module in holehe/modules/social_media/facebook.py demonstrates typical usage patterns, including CSRF token extraction and sequential POST requests:


# holehe/modules/social_media/facebook.py – example module

async def facebook(email, client, out):
    # … build headers …

    # 1️⃣ GET the signup page (fetch CSRF token)

    response = await client.get(
        "https://www.facebook.com/accounts/emailsignup/",
        headers=headers,
    )
    # 2️⃣ POST the registration attempt

    check = await client.post(
        "https://www.facebook.com/api/v1/web/accounts/web_create_ajax/attempt/",
        data=data,
        headers=headers,
    )
    # … analyse response and append results to out …

Architectural Benefits of the Shared Client

Connection Pooling: Because all modules reuse the same AsyncClient instance, HTTP/2 and HTTP/1.1 connections remain open for subsequent requests, eliminating TCP handshake overhead when querying multiple platforms.

Consistent Timeout Handling: The timeout value specified via the --timeout CLI argument (defaulting to 10 seconds) applies uniformly to every module request through the shared client configuration in holehe/core.py.

Simplified Maintenance: Centralizing client construction means that modifications—such as adding proxy support, custom transport layers, or retry logic—require changes to only one location rather than dozens of individual modules.

Concurrency and Resource Management

Modules execute concurrently within a Trio nursery, yet all coroutines share the same client instance. This design ensures that connection pool limits and file descriptor usage remain bounded regardless of how many platforms are queried simultaneously.

Customizing Requests Within Modules

While the client instance is shared, individual modules retain full control over per-request customization. Modules typically import random user agents from holehe/localuseragent.py and inject them into request headers alongside site-specific tokens or cookies.

async def some_site(email, client, out):
    headers = {"User-Agent": "holehe/1.0"}
    resp = await client.get("https://example.com/api/check", headers=headers)
    data = resp.json()
    # … process data …

    out.append({"name": "example", "exists": data["found"]})

Summary

  • Single Client Instance: Holehe creates one httpx.AsyncClient in holehe/core.py at startup via maincore().
  • Dependency Injection: The launch_module helper passes the client to each module as the second positional argument.
  • Async Pattern: All modules are async coroutines that use await client.get() and await client.post().
  • Resource Efficiency: Shared connection pooling and TLS session reuse reduce overhead across hundreds of concurrent requests.
  • Centralized Configuration: Timeout values and future transport modifications are managed in one location without touching module code.

Frequently Asked Questions

What HTTP library does Holehe use for its async client?

Holehe uses httpx.AsyncClient for all asynchronous HTTP operations. This library provides full support for HTTP/2, connection pooling, and concurrent request handling, which aligns with Holehe's requirement to query multiple platforms simultaneously without blocking execution.

How does Holehe handle timeouts for network requests?

Timeouts are configured via the --timeout CLI argument and passed directly to the httpx.AsyncClient constructor in holehe/core.py. The default timeout is 10 seconds, and this value applies consistently to every request made by any module through the shared client instance.

Can individual modules modify the HTTP client configuration?

Modules receive the client as a parameter but do not modify its global configuration. Instead, they customize individual requests by passing headers, cookies, or data parameters to client.get() or client.post(). This ensures that connection pool settings remain stable while allowing per-site customization for user agents or CSRF tokens.

Why does Holehe use a single shared client instead of creating clients per module?

Using a single shared client enables connection pooling and TLS session reuse across all modules, significantly reducing network overhead when querying hundreds of platforms. It also centralizes configuration management, making it easier to implement global features like proxy support or custom retry logic in holehe/core.py without modifying individual modules.

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 →