Holehe Module Result Dictionary: Complete Schema and Usage Guide

Every Holehe module returns a standard Python dictionary with six fixed keys: name, rateLimit, exists, emailrecovery, phoneNumber, and others.

The Holehe osint (Open Source Intelligence) tool, developed by megadose, uses a consistent result format across all 120+ modules to report whether an email address is registered on various online services. This article explains the Holehe module result dictionary schema, shows how to access each field programmatically, and provides working code examples from the actual source code.

What Is the Holehe Module Result Dictionary

When you run Holehe—either from the command line or as a Python library—each service check produces a single dictionary. Every module in holehe/modules/ follows this exact pattern, making it easy to aggregate and analyze results across dozens of platforms.

The dictionary serves as the universal data contract between individual modules and the reporting engine in holehe/core.py. Regardless of whether you're checking Twitter, Instagram, or a niche transport service like BlaBlaCar, the output structure remains identical.

The Six Fields in Every Holehe Result Dictionary

Key Type Description
name str Module identifier matching the service (e.g., twitter, instagram, blablacar).
rateLimit bool True if the service blocked the request due to rate limiting.
exists bool True if the email is registered on that service.
emailrecovery str or None Partially masked recovery email, if exposed by the service.
phoneNumber str or None Partially masked recovery phone number, if exposed.
others any or None Extension point for additional module-specific data.

This schema is documented in the repository's README under the Module Output section and enforced by convention across all module implementations.

Where the Result Dictionary Is Built in the Source Code

Core Implementation Pattern

Each Holehe module constructs its result dictionary at the end of its main function. For example, in holehe/modules/social_media/twitter.py and holehe/modules/transport/blablacar.py, you'll see code following this pattern:

out.append({
    "name": "twitter",
    "rateLimit": is_rate_limited,
    "exists": account_found,
    "emailrecovery": masked_email,
    "phoneNumber": masked_phone,
    "others": None
})

The out parameter is a list passed by the caller (managed in holehe/core.py) that collects all result dictionaries for final aggregation.

Key Source Files

Working with Holehe Result Dictionaries in Python

Basic Programmatic Usage

import httpx
import trio
from holehe.modules.social_media.twitter import twitter

async def check_single_service(email: str):
    results = []
    
    async with httpx.AsyncClient() as client:
        await twitter(email, client, results)
    
    # Returns the standard 6-key dictionary

    return results[0]

# Execute

result = trio.run(check_single_service, "test@example.com")
print(result)

Expected output:

{
    'name': 'twitter',
    'rateLimit': False,
    'exists': True,
    'emailrecovery': None,
    'phoneNumber': None,
    'others': None
}

Processing Multiple Results

from holehe.core import import_submodules
from holehe.modules import module

async def check_email_full(email: str):
    async with httpx.AsyncClient() as client:
        modules = import_submodules()
        all_results = []
        
        for mod in modules:
            out = []
            try:
                await mod(email, client, out)
                all_results.extend(out)
            except Exception:
                continue  # Skip failed modules

        
        # Filter and analyze results

        found_accounts = [r for r in all_results if r['exists']]
        rate_limited = [r for r in all_results if r['rateLimit']]
        
        return {
            'total_checked': len(all_results),
            'accounts_found': len(found_accounts),
            'rate_limited_services': [r['name'] for r in rate_limited],
            'recovery_emails': [r['emailrecovery'] for r in all_results if r['emailrecovery']]
        }

Checking for Recovery Information

The emailrecovery and phoneNumber fields are particularly valuable for osint investigations. Services like Instagram occasionally expose partial recovery data:

async def check_recovery_data(email: str):
    from holehe.modules.social_media.instagram import instagram
    
    results = []
    async with httpx.AsyncClient() as client:
        await instagram(email, client, results)
    
    result = results[0]
    
    if result['exists']:
        print(f"Account found on {result['name']}")
        
        if result['emailrecovery']:
            print(f"  Recovery email pattern: {result['emailrecovery']}")
            # Example output: "ex****e@gmail.com"

        
        if result['phoneNumber']:
            print(f"  Recovery phone pattern: {result['phoneNumber']}")
            # Example output: "0*******78"

    
    return result

Interpreting Field Values Correctly

Understanding rateLimit vs exists

These boolean flags operate independently:

  • rateLimit: True – The service blocked the request; exists is unreliable.
  • exists: True – Confirmed registration, but check if rateLimit is False.
  • Both False – Confirmed no account found (or service unavailable).

Always check rateLimit before trusting exists:

def is_confirmed_account(result: dict) -> bool:
    return result['exists'] and not result['rateLimit']

The others Extension Field

While currently None in most modules, others allows future expansion without breaking the schema. Custom modules can use it to return:

  • Profile URLs
  • Username handles
  • Account creation dates
  • Geo-location hints

Maintain backward compatibility by keeping the six core fields present even when extending.

Summary

  • Every Holehe module returns identical dictionary keys: name, rateLimit, exists, emailrecovery, phoneNumber, and others.
  • The schema is enforced by convention across all modules in holehe/modules/ and documented in README.md.
  • holehe/core.py orchestrates execution while individual service modules in social_media/, transport/, and other categories implement the format.
  • Programmatic access requires passing an out list that receives result dictionaries; use httpx.AsyncClient for HTTP handling.
  • Recovery data fields (emailrecovery, phoneNumber) contain masked patterns, not full credentials.
  • Always validate rateLimit before trusting positive exists results.

Frequently Asked Questions

What does rateLimit: True mean in a Holehe result dictionary?

A True value indicates the target service blocked the request due to too many queries from your IP address. When rateLimit is True, the exists field becomes unreliable—you cannot determine whether the account exists because the service refused to respond. Wait before retrying or rotate your IP address.

Can Holehe result dictionaries contain additional custom keys?

No. All modules must return exactly the six specified keys to maintain compatibility with holehe/core.py and downstream tools. The others field exists specifically for extensibility—place any supplementary data there rather than adding new top-level keys.

How do I extract just the services where an account exists?

Filter the results list using a list comprehension that checks both exists and rateLimit:

confirmed = [
    r['name'] for r in results 
    if r['exists'] and not r['rateLimit']
]

This pattern appears throughout the Holehe codebase when generating summary reports.

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 →