How Holehe's CSV Export Works and What Data It Includes

Holehe's CSV export is triggered by the -C/--csv flag and writes all OSINT scan results to a timestamped UTF-8 file using the export_csv() function in holehe/core.py.

When running email reconnaissance with holehe, you can persist findings to a structured CSV file for further analysis, reporting, or integration with other tools. According to the megadose/holehe source code, this export mechanism is lightweight yet comprehensive, capturing every data point returned by the 120+ supported modules.

How to Enable CSV Export in Holehe

Command-Line Usage

Pass the -C or --csv flag when executing holehe from the terminal:

$ holehe victim@example.com -C

The tool executes all modules, aggregates results, and writes them to a filename with the pattern holehe_<timestamp>_<email>_results.csv. Upon completion, holehe prints the full path to the exported file.

Where the Flag Is Parsed

The argument is defined in holehe/core.py at lines 192-194:

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

When args.csvoutput evaluates to True, the main execution flow calls export_csv(data, args, email) immediately after all modules complete.

The export_csv Function: Implementation Details

The core logic resides in holehe/core.py at lines 54-64:

def export_csv(data, args, email):
    if args.csvoutput:
        timestamp = int(time.time())
        filename = f"holehe_{timestamp}_{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(f"All results have been exported to {filename}")

Key implementation characteristics:

  • Timestamped filenames prevent collisions when scanning the same target multiple times
  • newline='' ensures Windows compatibility by suppressing extra blank lines
  • csv.DictWriter maps dictionary keys directly to CSV columns
  • UTF-8 encoding handles international characters in email addresses and response data

What Data Fields the CSV Contains

Each row in the exported CSV represents one module's execution result. The column headers derive dynamically from data[0].keys(), ensuring the CSV structure always matches the internal data format.

Field Description Example Values
name Internal module identifier twitter, gmail, adobe
domain Target service domain twitter.com, adobe.com
rateLimit Boolean indicating throttling status True, False
exists Boolean indicating account discovery True (found), False (not found)
emailrecovery Obfuscated recovery email v***@gmail.com, None
phoneNumber Obfuscated recovery phone +1 ***-***-1234, None
others Miscellaneous metadata Full name, signup date, location, etc.

These fields are populated by individual modules in holehe/modules/ and collected into the data list passed to export_csv().

Programmatic CSV Export Example

You can also invoke export_csv() directly when embedding holehe in Python applications:

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

async def scan_and_export(email: str):
    # Load all OSINT modules

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

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

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

# Execute the scan

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

This approach mirrors the CLI behavior while allowing custom result processing before export.

CSV vs. Terminal Output: Key Differences

  • Terminal output renders results as formatted tables with color-coded status indicators
  • CSV export preserves the complete raw dataset including all metadata fields, even when exists=False
  • CSV files include rate-limited and failed attempts, giving you visibility into data quality and coverage gaps

Summary

  • Holehe's CSV export is implemented in the export_csv() function within holehe/core.py (lines 54-64)
  • Activation requires the -C/--csv flag parsed at lines 192-194 of the same file
  • Output filenames follow the pattern holehe_<timestamp>_<email>_results.csv
  • Seven standard fields capture module results: name, domain, rateLimit, exists, emailrecovery, phoneNumber, and others
  • The csv.DictWriter class generates headers dynamically from result dictionary keys

Frequently Asked Questions

Does holehe append to existing CSV files or overwrite them?

Holehe creates a new file with a Unix timestamp on every export, so existing files are never modified or overwritten. This design ensures historical scan preservation without manual file management.

What happens if no accounts are found—will the CSV still be created?

Yes. The CSV is generated regardless of findings, containing rows where exists=False for all queried services. This negative data is valuable for confirming account absence across platforms.

Can I customize the CSV filename or output directory?

The current implementation does not expose filename or path configuration through CLI arguments. To customize output locations, use the programmatic API and modify the filename variable in export_csv() before the file open operation.

Why does the CSV contain None values for some fields?

None appears when a service either does not provide recovery contact information or the module failed to extract it. The others field is particularly variable—populated only when modules return additional metadata beyond the standard schema.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →