# How to Use the holehe CLI to Check Email Availability Across 200+ Services

> Easily check email availability on over 200 services with the holehe CLI. Discover if an email is registered across platforms using this fast Python tool.

- Repository: [Palenath/holehe](https://github.com/megadose/holehe)
- Tags: how-to-guide
- Published: 2026-09-08

---

**The holehe CLI is a Python-based command-line tool that checks whether an email address is registered on hundreds of online services by running asynchronous HTTP requests through modules defined in `holehe/modules/**`.**

The holehe tool, maintained in the `megadose/holehe` repository, provides efficient **email availability checking** without conducting brute-force attacks or password recovery attempts. It queries social media platforms, forums, and e-commerce sites concurrently to determine if an email address exists in their user databases. Understanding how to leverage this CLI requires examining its entry point configuration, argument parsing logic, and asynchronous execution model.

## Installation and CLI Entry Point

Installing holehe via `pip install holehe` registers a console-script entry point that maps the `holehe` command to the `main()` function in the codebase.

According to the source code in [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py), the following entry point declaration creates the CLI executable:

```python
entry_points={
    'console_scripts': [
        'holehe = holehe.core:main',
    ],
}

```

When you execute `holehe` in your terminal, Python invokes `holehe.core:main` located at [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) **lines 32-34**. This function serves as the central orchestrator for the entire email checking workflow.

## Core Architecture and Execution Flow

The holehe CLI operates through a modular architecture that dynamically discovers service checkers and executes them concurrently using the **trio** async library.

### Entry Point and Argument Parsing

The `main()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) begins by parsing command-line arguments through an `ArgumentParser` instance defined at **lines 80-96**. The parser accepts the target email as a positional argument alongside several optional flags:

- **`--only-used`**: Filters output to display only services where the email is registered
- **`--no-color`**: Disables ANSI color codes for piping output to files
- **`--no-clear`**: Prevents screen clearing between status updates
- **`-NP`/`--no-password-recovery`**: Skips password recovery endpoints for faster execution
- **`-C`/`--csv`**: Exports results to a CSV file via `export_csv()` at **lines 54-64**
- **`-T`/`--timeout`**: Configures the HTTP request timeout in seconds

Before processing, the CLI validates the email format against the `EMAIL_FORMAT` regex pattern defined at [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) **lines 31-33**.

### Module Discovery and Loading

The CLI dynamically loads service modules rather than maintaining a static list. The `import_submodules()` function at **lines 37-48** scans the `holehe.modules` package tree, while `get_functions()` at **lines 50-64** introspects each module to extract callable check functions.

Each module in `holehe/modules/` (e.g., [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py) or [`holehe/modules/mails/google.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/mails/google.py)) implements a specific service check. The loader discovers over 200 such modules automatically, ensuring the tool queries the latest available endpoints without manual configuration updates.

### Asynchronous Execution

Holehe uses **trio** for structured concurrency, as implemented at [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) **lines 119-122**. The execution flow passes three arguments to each service function:

1. The target email address
2. An `httpx.AsyncClient` instance for HTTP communication
3. A shared output list for collecting results

The `TrioProgress` class in [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) provides a live progress bar that integrates with the trio event loop, while [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) supplies random User-Agent headers to evade basic bot detection.

After execution completes, `print_result()` at **lines 106-148** renders a color-coded summary categorizing responses as found (green), not found (red), rate-limited (yellow), or error (gray).

## Command-Line Options and Usage Examples

Basic usage requires only the target email address:

```bash
holehe alice@example.com

```

### Filtering Results

To display only services where the email is actively registered:

```bash
holehe alice@example.com --only-used

```

### Output Formatting

When redirecting output to a file or parsing with other tools, disable color codes:

```bash
holehe alice@example.com --no-color > results.txt

```

### Performance Optimization

Skip password recovery endpoints to reduce network overhead and execution time:

```bash
holehe alice@example.com --no-password-recovery

```

Adjust the HTTP timeout for slow connections:

```bash
holehe alice@example.com --timeout 20

```

### Data Export

Export the complete result set to CSV for further analysis:

```bash
holehe alice@example.com --csv

```

## Understanding the Output

The CLI categorizes each service response into four states:

- **Found** (green): The email is registered on the service
- **Not Found** (red): The email is not associated with an account
- **Rate Limited** (yellow): The service blocked the request due to throttling
- **Error** (gray): Network issues or unexpected responses prevented checking

Results appear in real-time as the trio event loop completes individual service checks, with the progress bar in [`holehe/instruments.py`](https://github.com/megadose/holehe/blob/main/holehe/instruments.py) providing visual feedback during execution.

## Summary

- The holehe CLI entry point is defined in [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) and maps to `holehe.core:main`, which orchestrates the entire checking workflow.
- [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) handles argument parsing at **lines 80-96**, email validation via `EMAIL_FORMAT`, and result formatting through `print_result()`.
- Service modules are dynamically loaded from `holehe/modules/**` using `import_submodules()` and `get_functions()`, supporting over 200 platforms.
- Asynchronous execution uses **trio** and `httpx.AsyncClient` for concurrent HTTP requests, with `TrioProgress` providing UI updates.
- Output filtering (`--only-used`), CSV export (`--csv`), and timeout configuration (`--timeout`) flags customize behavior for different operational requirements.

## Frequently Asked Questions

### How does holehe validate email addresses before checking services?

The `main()` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) validates the input against the `EMAIL_FORMAT` regex pattern defined at **lines 31-33**. If the email fails this validation, the CLI exits before initiating any network requests, preventing wasted resources on malformed addresses.

### Can I use holehe to check multiple email addresses simultaneously?

The current implementation in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) accepts only a single email address as the positional argument. To check multiple addresses, you must invoke the CLI separately for each email or script multiple sequential calls, as the `ArgumentParser` at **lines 80-96** defines the email parameter without nargs support for multiple values.

### What is the difference between `--no-password-recovery` and standard checks?

When you use the `-NP` or `--no-password-recovery` flag, the CLI excludes service modules that rely on password recovery endpoints to verify email existence. According to the argument parser configuration at **lines 80-96**, this reduces the number of HTTP requests and execution time, though it may decrease accuracy for certain platforms that only expose email validity through their password reset flows.

### How does holehe avoid being blocked by rate limiting?

The tool implements several evasion techniques: [`holehe/localuseragent.py`](https://github.com/megadose/holehe/blob/main/holehe/localuseragent.py) provides random User-Agent strings for each request, the trio-based async execution at **lines 119-122** manages concurrent connection pools efficiently, and the `--timeout` flag allows adjustment for services with aggressive rate limiting. However, frequent checks against the same services may still trigger rate limits, indicated by yellow "Rate Limited" status in the output.