# How Holehe Exports Scan Results to CSV: Complete Implementation Guide

> Learn how to export Holehe scan results to CSV with this implementation guide. Discover the core.py details and unlock efficient OSINT data management.

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

---

**Holehe's CSV export functionality is implemented in the `export_csv` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), which writes OSINT scan results to a timestamped UTF‑8 CSV file when the `-C/--csv` flag is provided.**

Holehe's CSV export functionality allows security researchers and OSINT investigators to persist email reconnaissance results for further analysis. This article examines the complete implementation details of how the megadose/holehe repository converts scan data into structured CSV output, including the data schema, file naming conventions, and programmatic usage patterns.

## Where CSV Export Is Implemented

The entire CSV export pipeline lives in **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)**, specifically lines 54–64 for the write logic and lines 190–194 for argument parsing. The `export_csv` function serves as the single entry point for all CSV operations, making the codebase maintainable and predictable.

### The export_csv Function Signature and Behavior

The `export_csv` function accepts three parameters: the scan results list (`data`), the parsed arguments object (`args`), and the target email address. It conditionally executes only when `args.csvoutput` evaluates to `True`.

```python

# From holehe/core.py lines 54-64

def export_csv(data, args, email):
    if args.csvoutput:
        filename = "holehe_" + str(int(time.time())) + "_" + email + "_results.csv"
        with open(filename, "w", newline='', encoding='utf-8') as f:
            fc = csv.DictWriter(f, fieldnames=data[0].keys())
            fc.writeheader()
            fc.writerows(data)
            print("All results have been exported to " + filename)
            exit()

```

Key implementation decisions in this function include:

- **Timestamped filenames**: Uses `time.time()` converted to integer seconds to prevent collisions
- **Windows-compatible line endings**: Opens file with `newline=''` to suppress extra blank lines on Windows
- **Dynamic headers**: Derives column names from `data[0].keys()` ensuring schema flexibility
- **UTF‑8 encoding**: Explicit encoding declaration for international character support

## How the -C/--csv Flag Triggers Export

The command-line interface defines the CSV flag through `argparse` at lines 192–194 in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

```python

# From holehe/core.py lines 192-194

parser.add_argument("-C","--csv", default=False, required=False,
                    action="store_true", dest="csvoutput",
                    help="Create a CSV with the results")

```

When invoked, this flag sets `args.csvoutput = True`, which the main execution flow passes to `export_csv`. The `action="store_true"` pattern ensures the flag requires no additional value—its mere presence enables the feature.

## CSV Data Schema and Field Definitions

Each row in the exported CSV represents a single module's execution result. The `csv.DictWriter` serializes Python dictionaries into columns, with the following **standardized fields** across all modules:

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Internal module identifier (e.g., `twitter`, `gmail`, `adobe`) |
| `domain` | string | Target service domain (e.g., `twitter.com`, `gmail.com`) |
| `rateLimit` | boolean | `True` if the request encountered rate limiting |
| `exists` | boolean | `True` when an account exists for the queried email |
| `emailrecovery` | string or `None` | Partially obfuscated recovery email from the service |
| `phoneNumber` | string or `None` | Partially obfuscated recovery phone number |
| `others` | string or `None` | Additional metadata such as full name, account creation date, or country |

The `others` field demonstrates significant variance across modules—some services return rich metadata while others provide none. This is represented as `None` in the CSV when absent.

## Command-Line Usage Examples

### Basic CSV Export

Generate a CSV report from the command line:

```bash
holehe victim@example.com -C

```

Output:

```

All results have been exported to holehe_1723862123_victim@example.com_results.csv

```

### Combined with Other Flags

The CSV flag composes with standard Holehe options:

```bash
holehe target@domain.com -C --only-used --timeout 15

```

This exports only services where accounts exist (`exists=True`), with extended timeout.

## Programmatic CSV Export

For integration into larger Python workflows, instantiate the `Args` class and call `export_csv` directly:

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

async def run_email_reconnaissance(email: str):
    """Execute Holehe scan and export to CSV programmatically."""
    
    # Load all OSINT modules

    modules = import_submodules("holehe.modules")
    functions = get_functions(modules)
    
    # Collect results from each module

    results = []
    async with httpx.AsyncClient(timeout=10) as client:
        for func in functions:
            await func(email, client, results)
    
    # Configure and trigger CSV export

    class Args:
        csvoutput = True
    
    export_csv(results, Args(), email)

# Execute

trio.run(run_email_reconnaissance, "victim@example.com")

```

This pattern enables:
- Custom filtering before export
- Batch processing of multiple emails
- Integration with async application frameworks
- Automated reporting pipelines

## File Naming and Output Location

Holehe writes CSV files to the **current working directory** using this pattern:

```

holehe_<unix_timestamp>_<email>_results.csv

```

Example: `holehe_1723862123_victim@example.com_results.csv`

The timestamp provides chronological ordering and prevents accidental overwrites when scanning the same email repeatedly. Note that special characters in email addresses are preserved in filenames, which may require quoting when processing in shell environments.

## Integration with Module Result Structure

Each module in `holehe/modules/` returns a dictionary conforming to the CSV schema. For example, the Adobe module constructs results like:

```python

# Simplified from holehe/modules/software/adobe.py

return {
    "name": "adobe",
    "domain": "adobe.com",
    "rateLimit": False,
    "exists": True,
    "emailrecovery": "v***@gmail.com",
    "phoneNumber": "+1 5***12",
    "others": {"fullName": "John Doe", "createdDate": "2015-03-12"}
}

```

The `export_csv` function's use of `data[0].keys()` for fieldnames means modules can theoretically extend the schema, though consistency across modules ensures predictable CSV output.

## Error Handling and Edge Cases

The current implementation has specific behaviors worth noting:

- **Empty results**: If `data` is empty, `data[0].keys()` raises `IndexError`—the function assumes at least one result
- **Exit on completion**: `export_csv` calls `exit()` after writing, terminating the entire process
- **No append mode**: Each invocation creates a new file; no mechanism exists to append to existing CSVs

## Summary

- **Primary location**: [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 54–64 contain the `export_csv` function that implements CSV export functionality
- **Trigger mechanism**: The `-C/--csv` command-line flag, parsed at lines 192–194, activates export via `args.csvoutput`
- **File format**: UTF‑8 encoded CSV with headers dynamically generated from result dictionary keys
- **Output filename pattern**: `holehe_<timestamp>_<email>_results.csv` in the current working directory
- **Data schema**: Seven standard fields (`name`, `domain`, `rateLimit`, `exists`, `emailrecovery`, `phoneNumber`, `others`) populated by each OSINT module
- **Implementation library**: Python's standard `csv.DictWriter` with `newline=''` for cross-platform compatibility

## Frequently Asked Questions

### What information does Holehe include in CSV exports?

Holehe CSV exports contain seven fields per service checked: the module name, domain, rate limit status, account existence boolean, recovery email and phone (obfuscated), and miscellaneous metadata. These correspond exactly to the internal result dictionaries generated by each OSINT module in `holehe/modules/`.

### How do I disable CSV export when running Holehe programmatically?

Set `csvoutput = False` in your arguments object. The `export_csv` function returns immediately without file operations when this attribute is falsy, allowing normal continuation of program execution without the `exit()` call.

### Can I customize the CSV filename or location?

The current implementation in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) hardcodes the filename pattern and current working directory. To customize, modify the `filename` assignment at line 58 or wrap `export_csv` with your own function that renames the file post-creation.

### Why does Holehe exit after CSV export?

The `exit()` call at line 64 of [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) ensures clean termination after successful export in CLI contexts. For programmatic use where continuation is required, either avoid calling `export_csv` directly or catch `SystemExit` and suppress it.