# How Holehe's CSV Export Functionality Works: Complete Technical Guide

> Understand Holehe's CSV export functionality. Learn how the export_csv function generates timestamped UTF-8 files with account existence, rate limits, and recovery data.

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

---

**Holehe's CSV export is handled by the `export_csv` function in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py), which writes scan results to a timestamped UTF-8 CSV file containing 7 standardized fields including account existence, rate limits, and recovery information.**

Holehe is a popular OSINT tool for checking email address presence across hundreds of websites. When you need to preserve scan results for reporting or further analysis, the **CSV export functionality** provides a portable, structured format that captures every finding. This guide examines how the export system works, what data it captures, and how to use it both from the command line and programmatically.

## How to Enable CSV Export in Holehe

The CSV feature is triggered by the `-C` or `--csv` flag when running Holehe from the command line. According to the megadose/holehe source code, this flag is defined in the argument parser at line 192-194 of [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py):

```python
parser.add_argument("-C","--csv", action='store_true', dest="csvoutput",
                    help="Create a csv with the results")

```

When `args.csvoutput` evaluates to `True`, Holehe automatically invokes `export_csv()` after completing the email scan across all modules.

### Command Line Usage

```bash

# Basic CSV export

$ holehe victim@example.com -C
All results have been exported to holehe_1723862123_victim@example.com_results.csv

# Combine with other flags

$ holehe victim@example.com -C --no-tqdm --only-used

```

The filename follows a predictable pattern: `holehe_<timestamp>_<email>_results.csv`. This naming convention prevents overwrites and preserves scan context.

## The export_csv Function Implementation

The core CSV logic resides in `export_csv` at lines 54-64 of [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py). Here is the actual implementation structure:

```python
def export_csv(data, args, email):
    if args.csvoutput:
        name = "holehe_" + str(int(time.time())) + "_" + str(email) + "_results.csv"
        with open(name, 'w', newline='', encoding='utf-8') as f:
            if data:
                fc = csv.DictWriter(f, fieldnames=data[0].keys())
                fc.writeheader()
                fc.writerows(data)

```

Key implementation details from the source:

- **`newline=''`**: Prevents extra blank lines on Windows systems
- **`encoding='utf-8'`**: Ensures universal character compatibility
- **`csv.DictWriter`**: Maps dictionary keys directly to CSV columns
- **Dynamic headers**: `fieldnames=data[0].keys()` guarantees column order matches the internal data structure

The function requires no explicit return; it writes the file and allows normal program termination.

## What Data Holehe's CSV Export Includes

Each row in the exported CSV represents one module's result. The **7 standard fields** captured in every scan are:

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

These fields originate from individual modules in `holehe/modules/*`. Each module returns a standardized dictionary that `export_csv` aggregates into the final dataset.

### Sample CSV Output Structure

```csv
name,domain,rateLimit,exists,emailrecovery,phoneNumber,others
twitter,twitter.com,False,True,vi***@gmail.com,+1 *** *** 1234,"{'fullname': 'John Doe'}"
gmail,gmail.com,False,True,None,None,None
adobe,adobe.com,False,False,None,None,None
github,github.com,True,False,None,None,None

```

Note the **rate limit indicator** on the GitHub row—this distinction matters for result interpretation.

## Programmatic CSV Export with Holehe

You can leverage `export_csv` directly in Python scripts for custom workflows. This approach requires constructing a compatible argument object:

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


async def scan_and_export(email: str, output_csv: bool = True):
    """
    Run Holehe scan and optionally export to CSV.
    """
    # Load all OSINT modules

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

    results = []
    async with httpx.AsyncClient(timeout=10) as client:
        for func in functions:
            await func(email, client, results)
    
    # Export to CSV if requested

    if output_csv:
        class Args:
            csvoutput = True
        
        export_csv(results, Args(), email)
        print(f"Exported {len(results)} results for {email}")
    
    return results


# Execute scan

trio.run(scan_and_export, "target@example.com")

```

This pattern is useful for:

- **Batch processing** multiple email addresses
- **Integrating** Holehe into larger reconnaissance pipelines
- **Custom filtering** before export

## CSV vs. JSON Output: Key Differences

Holehe supports multiple output formats. Understanding CSV's specific characteristics helps you choose appropriately:

| Aspect | CSV Export | JSON Export |
|--------|-----------|-------------|
| **Human readability** | Excellent in spreadsheet tools | Requires parsing |
| **Schema flexibility** | Fixed column order from `data[0].keys()` | Preserves nested structures in `others` |
| **File size** | Smaller for flat data | Larger due to repeated keys |
| **Nested data handling** | `others` field flattened as string | Native nested object support |
| **Tool compatibility** | Excel, Google Sheets, pandas | APIs, MongoDB, jq |

The `others` field in CSV contains serialized dictionary data—parse it with `ast.literal_eval` or `json.loads` if you need programmatic access to nested values.

## Source Files and Reference

The **Holehe CSV export functionality** spans these key locations in the megadose/holehe repository:

- **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 54-64**: `export_csv` function implementation
- **[`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py) lines 190-194**: `-C/--csv` argument parsing
- **`holehe/modules/*`**: Module result generation (e.g., [`adobe.py`](https://github.com/megadose/holehe/blob/main/adobe.py), [`twitter.py`](https://github.com/megadose/holehe/blob/main/twitter.py))
- **[`README.md`](https://github.com/megadose/holehe/blob/main/README.md) lines 73-84**: Output format documentation

For the most current implementation, verify against the master branch as the tool actively evolves.

## Summary

- **CSV export is triggered by `-C/--csv`** and handled by `export_csv()` in [`holehe/core.py`](https://github.com/megadose/holehe/blob/main/holehe/core.py)
- **Auto-generated filenames** include timestamps: `holehe_<timestamp>_<email>_results.csv`
- **Seven standardized fields** capture module name, domain, rate limits, account existence, recovery email, phone number, and miscellaneous data
- **UTF-8 encoding with `newline=''`** ensures cross-platform compatibility
- **Programmatic access** requires creating an `Args` class with `csvoutput = True`

## Frequently Asked Questions

### Does Holehe's CSV export include the raw HTTP responses?

No. The CSV contains only processed results—module identifiers, existence flags, and extracted metadata. Raw HTTP responses are not preserved; they are processed by each module in `holehe/modules/*` and distilled into the standardized 7-field structure before export.

### Can I customize which columns appear in the CSV output?

Not directly through command-line flags. The `export_csv` function dynamically builds headers from `data[0].keys()`, so column selection would require modifying the result dictionaries before calling `export_csv()` programmatically.

### What happens if all modules return rate limits?

The CSV still generates with all rows present. Each rate-limited module shows `rateLimit: True` and typically `exists: False` since the existence check could not complete. Review the `rateLimit` column to distinguish inconclusive results from confirmed negatives.

### Is the CSV format stable across Holehe versions?

The 7-field structure (`name`, `domain`, `rateLimit`, `exists`, `emailrecovery`, `phoneNumber`, `others`) has remained consistent, but verify against your installed version. The dynamic header generation in `export_csv` adapts to any new fields modules might add.