# How HTTP Clients Are Configured and Managed in Holehe Modules

> Discover how Holehe modules centralize HTTP client configuration using a single httpx.AsyncClient for connection pooling, TLS reuse, and consistent timeouts across all OSINT requests.

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

---

**Holehe centralizes HTTP client configuration in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/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.

```python

# 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`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/facebook.py) demonstrates typical usage patterns, including CSRF token extraction and sequential POST requests:

```python

# 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`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) and inject them into request headers alongside site-specific tokens or cookies.

```python
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`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/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`](https://github.com/megadose/holehe/blob/main/holehe/core.py) without modifying individual modules.