How Holehe Handles Rate Limiting: Exception-Based Detection in the Core Engine
Holehe treats any exception during a module's HTTP request as a rate-limit condition, automatically flagging the service with rateLimit: True instead of crashing the entire scan.
Holehe is an open-source email investigation tool that checks registration status across hundreds of websites. Understanding how it handles rate limiting is essential for interpreting results and avoiding false negatives when services temporarily block requests. This article examines the detection mechanism implemented in megadose/holehe.
The Core Detection Mechanism: Generic Exception Wrapping
Rate-limit detection in Holehe is centralized in holehe/core.py through the launch_module function. Rather than implementing per-service rate-limit logic, Holehe uses a broad exception handler that assumes any failure indicates throttling.
The launch_module Wrapper (Lines 66-78)
# holehe/core.py – launch_module
async def launch_module(module, email, client, out):
try:
await module(email, client, out)
except Exception: # any error → assumed rate-limit
name = str(module).split('<function ')[1].split(' ')[0]
out.append({
"name": name,
"domain": data[name],
"rateLimit": True, # flag set here
"error": True,
"exists": False,
"emailrecovery": None,
"phoneNumber": None,
"others": None})
The launch_module function receives four parameters:
module— the service-specific checking functionemail— the target email addressclient— a sharedhttpx.AsyncClientinstanceout— a list that accumulates results
When any exception is raised—from HTTP 429 responses to connection timeouts to DNS errors—the wrapper catches it generically and populates a standardized result dictionary with "rateLimit": True.
Visual Indicators in CLI Output
After all modules complete, print_result renders the rate-limit status in the terminal table. Services flagged as rate-limited appear with a yellow [x] marker.
The print_result Filter (Lines 22-26)
# holehe/core.py – print_result
if results["rateLimit"] and args.onlyused == False:
websiteprint = print_color("[x] " + results["domain"], "yellow", args)
print(websiteprint)
The [x] symbol distinguishes rate-limited services from:
[+]— email found/registered (green)[-]— email not found (red)
This visual encoding lets users immediately spot which services couldn't be verified due to throttling.
The frequent_rate_limit Hint Flag
Some modules declare a class-level or module-level variable frequent_rate_limit = True to indicate services known for aggressive throttling. This metadata appears only in raw JSON output and does not alter detection behavior.
Example: Wattpad Module
# holehe/modules/social_media/wattpad.py (lines 9-14)
frequent_rate_limit = True
async def wattpad(email, client, out):
# ... request logic ...
out.append({..., "rateLimit": True, ...})
Similar declarations exist in holehe/modules/transport/blablacar.py and other modules. These flags serve as documentation for users reviewing verbose output, not as runtime logic.
Practical Examples
CLI Usage Showing Rate Limits
$ holehe you@example.com
[+] Email used
[x] twitter.com ← rate-limit detected (yellow [x])
[-] facebook.com
[+] github.com
...
The [x] twitter.com entry indicates the Twitter check failed—likely due to HTTP 429 or connection timeout—and Holehe recorded it as rate-limited rather than unregistered.
Programmatic Inspection
from holehe.core import launch_module
import httpx, asyncio
async def demo(email):
async with httpx.AsyncClient() as client:
out = []
from holehe.modules.social_media import twitter
await launch_module(twitter.twitter, email, client, out)
print(out)
# [{'name': 'twitter', 'domain': 'twitter.com',
# 'rateLimit': True, 'error': True, 'exists': False, ...}]
asyncio.run(demo('you@example.com'))
The out list contains the rate-limit flag, allowing automated pipelines to distinguish between "email not found" and "check inconclusive due to throttling."
Key Source Files
| File | Purpose |
|---|---|
holehe/core.py |
Implements launch_module exception wrapper and print_result rendering; contains the primary rate-limit detection logic |
holehe/modules/social_media/twitter.py |
Typical module showing request patterns that may trigger rate-limit flags |
holehe/modules/social_media/wattpad.py |
Module with frequent_rate_limit = True hint flag for known-throttled services |
holehe/modules/transport/blablacar.py |
Additional example of the frequency hint flag |
Summary
- Holehe handles rate limiting through a generic exception wrapper in
launch_modulethat flags any failed request as"rateLimit": True - No per-service rate-limit logic exists—HTTP 429s, timeouts, and DNS failures are treated identically
- CLI output uses yellow
[x]markers to visually indicate throttled services frequent_rate_limithints document known-problematic services but don't affect detection- The shared
httpx.AsyncClientenables efficient concurrent requests while the central wrapper ensures graceful degradation
Frequently Asked Questions
What HTTP status codes trigger Holehe's rate-limit detection?
Holehe does not inspect status codes directly. Any exception raised during module execution—including but not limited to HTTP 429, connection timeouts, SSL errors, or DNS failures—triggers the generic exception handler in launch_module and sets "rateLimit": True. This design prioritizes robustness over precision.
Can I disable rate-limit detection or treat rate-limited services as "not found"?
No configuration option changes the rate-limit detection behavior. The launch_module function in holehe/core.py hardcodes the exception-to-rate-limit mapping. Users filtering results must post-process the output and interpret "rateLimit": True according to their needs.
Why do some modules set frequent_rate_limit = True?
This flag serves as documentation for services like Wattpad and Blablacar that are known to throttle aggressively. It appears only in verbose/JSON output and has no effect on the detection mechanism. The actual rate-limit flag still depends on whether the request raises an exception.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →