# How to Use Holehe to Check Email Availability: CLI and Python Guide

> Easily check email availability using holehe. Run commands or import into Python for fast OSINT checks on over 120 services.

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

---

**Run `holehe <email>` to check if an email address is already registered across 120+ online services, or import `holehe.core` into your Python scripts for programmatic OSINT checks.**

Holehe is a Python-based OSINT (Open Source Intelligence) tool maintained by megadose that probes social media platforms, shopping sites, and other online services to determine email availability. This guide explains both command-line and programmatic usage based on the holehe source code, including how to interpret results, filter output, and integrate the tool into your own applications.

## Installing Holehe

The fastest way to get started is via PyPI. The tool requires Python 3.6+.

```bash
pip3 install holehe

```

Verify the installation:

```bash
holehe --help

```

## CLI Usage: The Quick Email Check

The simplest way to use holehe to check email availability is with a single argument.

```bash
holehe test@example.com

```

Holehe performs the following steps internally, as defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

1. **Argument parsing** — extracts the email from `parser.add_argument("email", ...)` at lines 80-84
2. **Email validation** — validates format via `is_email` regex at lines 31-33
3. **Module discovery** — dynamically imports all modules in `holehe.modules` using `import_submodules` (lines 37-48)
4. **Concurrent execution** — runs service checks in parallel with **trio** and `httpx.AsyncClient`
5. **Result formatting** — displays colored output and optionally exports to CSV

### Understanding the Output

Each service returns a result that holehe renders with color-coded symbols:

| Symbol | Meaning | `exists` value |
|--------|---------|--------------|
| `[+]` | Account found | `True` |
| `[-]` | No account | `False` |
| `[x]` | Rate limited | varies |
| `[!]` | Error occurred | varies |

Example output:

```

[+] instagram
[-] twitter
[x] reddit
[!] error on some-site

```

The `exists` flag in the underlying dictionary determines whether the email is registered on that platform.

### CLI Options for Better Results

Filter to accounts only:

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

```

Export to CSV for reporting:

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

```

These flags are defined in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 84-93. Additional useful options include:

| Flag | Purpose |
|------|---------|
| `--no-color` | Disable colored output for piping |
| `--no-clear` | Preserve terminal history |
| `-NP / --no-password-recovery` | Skip password-recovery-based checks |
| `-T / --timeout <seconds>` | Override default 10-second HTTP timeout |

## Python API: Programmatic Email Checks

For integration into larger applications, import holehe's core functions directly. This approach gives you full control over result processing.

```python
import trio
import httpx
from holehe.core import import_submodules, get_functions


async def check_email_availability(email: str):
    """Check email registration status across all supported services."""
    # Discover all service modules

    modules = import_submodules("holehe.modules")
    websites = get_functions(modules)  # List of async callables

    
    results = []
    
    # Execute all checks concurrently

    async with httpx.AsyncClient(timeout=10) as client:
        async with trio.open_nursery() as nursery:
            for site in websites:
                nursery.start_soon(site, email, client, results)
    
    # Process and return structured results

    return sorted(results, key=lambda x: x.get("name", ""))


def run_check(email: str):
    """Synchronous wrapper for trio-based async execution."""
    return trio.run(check_email_availability, email)


# Example usage

if __name__ == "__main__":
    email = "test@example.com"
    results = run_check(email)
    
    for r in results:
        status = "registered" if r.get("exists") else "available"
        print(f"{r['domain']}: {status}")

```

Each service function follows the signature `async def <service>(email, client, out)` and appends a dictionary to `out` with these keys:

- `exists` — Boolean indicating registration status
- `name` — Human-readable service name
- `domain` — Service domain
- `rateLimit` — Whether the check was rate-limited
- `emailrecovery` — Recovery email if leaked
- `phoneNumber` — Phone number if leaked

## Customizing Checks for Specific Services

To check only specific platforms, filter the `websites` list before execution:

```python
from holehe.core import import_submodules, get_functions

modules = import_submodules("holehe.modules")
all_sites = get_functions(modules)

# Filter to social media only

target_services = {"instagram", "twitter", "reddit", "facebook"}
filtered_sites = [
    s for s in all_sites 
    if s.__name__.lower() in target_services
]

```

Individual service implementations reside in `holehe/modules/<category>/<service>.py` — for example, [`holehe/modules/social_media/instagram.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/instagram.py).

## Timeout and Performance Tuning

The default 10-second timeout per HTTP request can be adjusted via CLI or programmatically:

**CLI:**

```bash
holehe test@example.com -T 30

```

**Python:**

```python
async with httpx.AsyncClient(timeout=30) as client:
    # ... execute checks

```

Concurrent execution via trio's nursery pattern means all 120+ services complete in roughly the time of the slowest response, not the sum of all requests.

## Summary

- **Install** holehe with `pip3 install holehe` for immediate CLI access
- **Run `holehe <email>`** to check email availability across 120+ services with colored terminal output
- **Use `--only-used`** to see registered accounts only, `--csv` to export results
- **Import `holehe.core`** for programmatic access with `import_submodules()`, `get_functions()`, and trio-based async execution
- **Check the `exists` flag** in result dictionaries to determine registration status
- **Adjust timeout with `-T`** when targeting slow services or working with unreliable connections

## Frequently Asked Questions

### What does the `[+]` symbol mean in holehe output?

The `[+]` symbol indicates `exists: True` — meaning the email address is already registered on that service. Conversely, `[-]` means no account was found. The symbols are rendered by the CLI at [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 46-52 based on each module's returned dictionary.

### Can I use holehe without installing the CLI tool?

Yes. Install the package, then import `from holehe.core import import_submodules, get_functions` to run checks entirely within Python. This is useful for building custom OSINT pipelines or integrating email availability checks into larger applications.

### How does holehe check so many services simultaneously?

Holehe uses **trio** for structured concurrency and `httpx.AsyncClient` for async HTTP requests. As shown in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 13-23, all service functions launch concurrently in a `trio.open_nursery()` block, sharing a single HTTP client with configurable timeout.

### Why do some services show `[x]` or `[!]` instead of `[+]` or `[-]`?

`[x]` means the service rate-limited your request (`rateLimit: True` in the result dict). `[!]` indicates an unexpected error during the check. Neither confirms nor denies email registration — you may need to retry with different IP addressing or adjust the timeout.