# How to Use Holehe from the Command Line: A Complete CLI Guide

> Master Holehe from the command line. Run holehe <email> to check over 120 services, filter results, export CSV, and more. Your essential CLI guide.

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

---

**Run `holehe <email>` to check if an email is registered on 120+ services, with options to filter results, disable colors, export CSV, and adjust timeouts.**

Holehe is a Python-based OSINT tool developed by **megadose/holehe** that performs asynchronous email-checking across hundreds of online platforms. When installed via pip, it registers a console script that launches an async pipeline using **Trio** and **httpx** to query every supported module in parallel. This guide covers all command-line options, flags, and practical workflows.

---

## Installation and Basic Usage

### Installing Holehe

Install from PyPI to register the `holehe` command:

```bash
pip install holehe

```

The [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) file declares the console script entry point:

```python

# In setup.py

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

```

This maps the `holehe` command to `holehe.core:main`, which [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) implements.

### Running Your First Check

Execute a basic email lookup:

```bash
holehe test@example.com

```

This triggers the full pipeline: argument parsing → dynamic module discovery → parallel async execution → formatted terminal output. Results display as a colored table showing which services have an account registered to that email.

---

## Core CLI Flags and Options

The `argparse`-based parser in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 80–96) supports these flags:

| Flag | Purpose | Example |
|------|---------|---------|
| `--only-used` | Show only services where the email exists | `holehe email@domain.com --only-used` |
| `--no-color` | Disable ANSI colors (useful for logs/piping) | `holehe email@domain.com --no-color` |
| `--csv` | Export results to timestamped CSV file | `holehe email@domain.com --csv` |
| `--no-password-recovery` | Skip password recovery checks (faster) | `holehe email@domain.com --no-password-recovery` |
| `--timeout` | Set request timeout in seconds (default: 10) | `holehe email@domain.com --timeout 20` |

### Combined Flag Example

```bash
holehe investigator@protonmail.com --only-used --no-color --csv --timeout 15

```

---

## Output Formats and Result Handling

### Colored Terminal Output

By default, `print_result` in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) (lines 6–51) renders a colored table with columns for:

- **Service name**
- **Exists** (account found)
- **Email recovery** (password reset available)
- **Phone** (number recovery possible)
- **Others** (additional metadata)

### CSV Export

The `--csv` flag triggers `export_csv`, creating a file named:

```

holehe_<timestamp>_email@domain.com_results.csv

```

This preserves all structured data for further analysis or reporting.

---

## How the CLI Works Internally

Understanding the architecture helps troubleshoot issues and extend functionality.

### 1. Entry Point: `holehe.core:main`

Located in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), the `main()` function coordinates:

```python

# Simplified from holehe/core.py

def main():
    parser = argparse.ArgumentParser()
    # ... argument definitions (lines 80-96) ...

    args = parser.parse_args()
    
    # Dynamic module loading via import_submodules (lines 37-47)

    modules = import_submodules(holehe.modules)
    
    # Async execution with Trio

    trio.run(run_async, modules, args)

```

### 2. Dynamic Module Loading

The `import_submodules` function (lines 37–47) introspects `holehe.modules` to discover all site-specific checkers:

```python

# From holehe/core.py

def import_submodules(package, recursive=True):
    """Import all submodules of a module, recursively."""
    results = {}
    for _, name, is_pkg in pkgutil.walk_packages(package.__path__):
        full_name = package.__name__ + '.' + name
        results[full_name] = importlib.import_module(full_name)
        if recursive and is_pkg:
            results.update(import_submodules(full_name))
    return results

```

### 3. Parallel Async Execution

Each module runs concurrently via `trio.open_nursery`:

```python

# From holehe/core.py launch_module & async loop (lines 66-73)

async def main_loop(email, modules, client, args):
    async with trio.open_nursery() as nursery:
        for module in modules:
            nursery.start_soon(launch_module, module, email, client, out)

```

Modules are located under `holehe/modules/` with structure like:
- [`holehe/modules/social_media/twitter.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/twitter.py)
- [`holehe/modules/social_media/instagram.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/social_media/instagram.py)
- [`holehe/modules/music/spotify.py`](https://github.com/megadose/holehe/blob/main/holehe/modules/music/spotify.py)

Each module exposes an async function returning a standardized dictionary:

```python
{
    "name": "twitter",
    "domain": "twitter.com",
    "method": "password_recovery",
    "frequent_rate_limit": False,
    "rateLimit": False,
    "exists": True,
    "emailrecovery": "t***@example.com",
    "phoneNumber": None,
    "others": None
}

```

---

## Practical Command-Line Workflows

### Workflow 1: Quick Triage Investigation

Check only confirmed accounts, save to CSV, disable colors for log files:

```bash
holehe target@company.com --only-used --csv --no-color

```

### Workflow 2: Stealth/Fast Scanning

Skip password recovery endpoints to reduce noise and time:

```bash
holehe target@protonmail.com --no-password-recovery --timeout 5

```

### Workflow 3: Bulk Processing

Pipe multiple emails through a loop:

```bash
for email in $(cat emails.txt); do
    holehe "$email" --only-used --csv
done

```

---

## Troubleshooting Common Issues

| Issue | Cause | Solution |
|-------|-------|----------|
| `command not found: holehe` | Script not in PATH | Reinstall with `pip install --force-reinstall holehe` |
| All results show `rateLimit: True` | Too many concurrent requests | Increase `--timeout` or reduce request frequency |
| No color output in terminal | `TERM` environment or piping | Check terminal supports ANSI; use explicit `--no-color` if piping |
| CSV file not created | Permission error in working directory | Run from writable directory or specify full path |

---

## Summary

- **Basic execution**: `holehe <email>` runs all 120+ checks with colored table output.
- **Key flags**: `--only-used`, `--no-color`, `--csv`, `--no-password-recovery`, `--timeout`.
- **Architecture**: Entry point at [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py) → `holehe.core:main` → `argparse` → `import_submodules` → Trio async loop → `print_result`/`export_csv`.
- **Modules**: Individual files under `holehe/modules/*` implement site-specific checks.
- **Performance**: Concurrent execution via `trio.open_nursery` with configurable timeouts.

---

## Frequently Asked Questions

### How do I install Holehe for command-line use?

Install via pip: `pip install holehe`. This registers the `holehe` console script in your PATH, mapping to `holehe.core:main` as defined in [`setup.py`](https://github.com/megadose/holehe/blob/main/setup.py). For development, clone the repository and run `pip install -e .` from the source directory.

### Can I run Holehe without installing it?

Yes. Clone the repository and execute `python -m holehe.core <email>` from the project root, or run `python holehe/core.py <email>` directly. However, installing via pip is recommended to ensure all dependencies and module paths resolve correctly.

### What does the `--only-used` flag actually filter?

It suppresses services where the email returns `exists: False`, showing only platforms with confirmed accounts. This reduces noise in investigations with many negative results. The filter applies after results are collected, so all modules still execute.

### How does Holehe avoid rate limiting?

It doesn't inherently throttle requests. Each module runs concurrently through `trio.open_nursery` with a default 10-second timeout. If you encounter rate limits, increase `--timeout` or add delays between batches. Some modules flag `frequent_rate_limit: True` in their return dictionaries to indicate sensitive endpoints.