# How Holehe Detects and Handles Rate Limiting from Target Websites During Email Checks

> Learn how Holehe detects and handles rate limiting from target websites during email checks. Discover its HTTP 429 response detection and throttling mechanisms for efficient email verification.

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

---

**Holehe detects rate limiting by checking for HTTP 429 responses in each service module and handles throttling by recording `rateLimit: True` in the result dictionary, with a fallback exception handler in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) that catches network errors and marks them as rate-limited.**

Holehe is an open-source email verification tool that checks hundreds of websites for account existence. When target services throttle these requests, the tool implements a consistent rate-limit detection pattern across its modular architecture to ensure accurate reporting and graceful degradation.

## How Holehe Detects HTTP 429 Rate Limits in Service Modules

Each Holehe module implements its own rate-limit detection logic. The standard approach checks for **HTTP status code 429** ("Too Many Requests") after making a request to the target endpoint.

Consider the Vivino module in [`holehe/modules/shopping/vivino.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/vivino.py). When the POST request to `https://www.vivino.com/api/login` returns a 429 status, the module constructs a result dictionary with `rateLimit: True`:

```python
if response.status_code == 429:
    out.append({
        "name": name,
        "domain": domain,
        "method": method,
        "frequent_rate_limit": frequent_rate_limit,
        "rateLimit": True,          # ← rate-limit detected

        "exists": False,
        "emailrecovery": None,
        "phoneNumber": None,
        "others": None
    })

```

Source: [holehe/modules/shopping/vivino.py](https://github.com/megadose/holehe/blob/master/holehe/modules/shopping/vivino.py#L28-L31)

The **Tumblr module** follows the same pattern. When the API returns `{"meta":{"status":429,"msg":"Limit Exceeded"},"response":[]}`, it records the rate-limit condition:

```python
else: #429 {"meta":{"status":429,"msg":"Limit Exceeded"},"response":[]}
    out.append({
        "name": name,
        "domain": domain,
        "method": method,
        "frequent_rate_limit": frequent_rate_limit,
        "rateLimit": True,
        ...
    })

```

Source: [holehe/modules/social_media/tumblr.py](https://github.com/megadose/holehe/blob/master/holehe/modules/social_media/tumblr.py#L91-L93)

## The `frequent_rate_limit` Flag for High-Throttling Services

Modules that anticipate regular throttling set **`frequent_rate_limit=True`** in their result dictionaries. This metadata helps users understand which services consistently enforce strict rate limits versus those that rarely throttle. The flag appears in the same result structure as `rateLimit`, providing context about the service's typical behavior.

## Fallback Exception Handling in `launch_module`

When a module throws an unexpected exception—such as a network timeout, connection reset, or DNS failure—the central dispatcher **`launch_module`** in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) catches it and records an error condition:

```python
except Exception:
    out.append({
        "name": name,
        "domain": data[name],
        "rateLimit": False,
        "error": True,
        ...
    })

```

Source: [holehe/core.py](https://github.com/megadose/holehe/blob/master/holehe/core.py#L66-L73)

This ensures that even when rate limiting manifests as connection failures rather than clean HTTP 429 responses, the failure is captured and reported rather than crashing the entire scan.

## CLI Visualization of Rate-Limited Services

Holehe displays rate-limited services with a yellow **`[x]`** marker in terminal output, distinct from negative results `[-]` and positive matches `[+]`. The `print_result` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) implements this visual differentiation, allowing users to immediately identify which checks were blocked by throttling.

```bash

# Run Holehe against an email address

holehe user@example.com

# Sample output (rate-limited services shown with [x])

[x] twitter.com
[-] amazon.com
[+] gmail.com

```

## Programmatic Rate-Limit Handling

When integrating Holehe into Python applications, rate-limit information is accessible through the result dictionary:

```python

# Using Holehe programmatically

import httpx, trio
from holehe.core import launch_module

async def check(email):
    async with httpx.AsyncClient(timeout=10) as client:
        out = []
        await launch_module(your_module, email, client, out)
        print(out)   # will contain {"rateLimit": True} when throttled

```

Applications can filter results by checking the `rateLimit` boolean to implement retry logic, adjust request timing, or exclude throttled services from final reports.

## Summary

- **HTTP 429 detection**: Each module checks `response.status_code == 429` to identify explicit rate limiting
- **`rateLimit: True`**: Standard flag recorded in result dictionaries when throttling is detected
- **`frequent_rate_limit`**: Additional metadata for services with known aggressive throttling
- **`launch_module` exception handler**: Catches network failures and unexpected errors, preventing scan interruption
- **Visual feedback**: CLI displays `[x]` in yellow for rate-limited services

## Frequently Asked Questions

### What HTTP status code does Holehe use to detect rate limiting?

Holehe primarily uses **HTTP 429** ("Too Many Requests") as the definitive signal for rate limiting. Individual modules implement this check after receiving responses from target endpoints, as seen in [`holehe/modules/shopping/vivino.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/shopping/vivino.py) and [`holehe/modules/social_media/tumblr.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/tumblr.py).

### Does Holehe automatically retry when rate limited?

No. According to the source code in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), Holehe does not implement automatic retry logic for rate-limited requests. The tool records the rate-limit condition via `rateLimit: True` and continues to the next service. Users must manually rerun checks for throttled services after an appropriate delay.

### How can I identify which services frequently rate-limit?

Check the **`frequent_rate_limit`** boolean in result dictionaries. Modules that commonly encounter throttling set this flag to `True`, providing metadata about the service's typical behavior. This helps distinguish between occasional rate limits and systematically restrictive platforms.

### What happens if a module crashes during execution?

The **`launch_module`** dispatcher in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) wraps each module call in a try-except block. Uncaught exceptions trigger the generic handler, which appends a result with `error: True` to the output list. This ensures that a single module failure does not terminate the entire email verification scan.