How Holehe Handles Rate Limiting and What to Do When Rate Limited
Holehe marks rate-limited services with a yellow [x] indicator and continues scanning without aborting, letting you retry individual services later or change your IP address when many services throttle you.
Holehe is an open-source email OSINT tool by Tristan Granier (megadose/holehe) that checks whether an email address exists on thousands of online services. When services return HTTP 429 "Too Many Requests" responses, the tool implements a graceful degradation strategy rather than failing hard. This article explains exactly how rate limiting detection works in the source code and what actions you should take based on the frequency of [x] markers in your output.
How Holehe Detects and Reports Rate Limiting
Per-Module Rate Limit Detection
Each service-specific module in holehe/modules/ is responsible for catching rate limit responses. When a service returns HTTP 429 or equivalent throttling signals, the module returns a standardized dictionary with rateLimit set to True.
From holehe/modules/transport/blablacar.py and similar modules, the pattern follows:
{
"name": "blablacar",
"domain": "blablacar.com",
"rateLimit": True, # ← Throttling detected
"error": False,
"exists": False,
"emailrecovery": None,
"phoneNumber": None,
"others": None,
}
The module aborts its specific check immediately upon detecting the limit—no retries are attempted within the module itself. This design prevents hammering already-throttled endpoints.
Central Orchestration in core.py
The main execution logic in holehe/core.py handles all module results uniformly. During output generation in the print_result function, rate-limited entries receive special visual treatment:
if results["rateLimit"] and args.onlyused == False:
websiteprint = print_color("[x] " + results["domain"], "yellow", args)
print(websiteprint)
Key characteristics of this approach:
- Non-blocking: The scan continues through all remaining modules
- Visual distinction: Yellow
[x]differentiates rate limits from[+](found),[-](not found), and[!](error) - Data preservation: Rate-limited results appear in CSV exports with
rateLimit=Truefor later analysis
What to Do When You See [x] Rate Limit Markers
Scenario 1: Isolated [x] Markers (1–3 Services)
Action: None required. The scan completed successfully for all other services.
Re-run selectively for specific services if needed:
# Basic scan showing rate-limited services
holehe alice@example.com
# Output shows:
# [+] github.com
# [-] twitter.com
# [x] spotify.com ← Rate limited, retry later if needed
Scenario 2: Widespread [x] Markers (Many Services)
Cause: Your source IP address is being globally throttled, likely by CDN-level protection (Cloudflare, Akamai) or shared infrastructure across services.
Immediate actions:
-
Change your network identity
# Example: Route through VPN/proxy proxychains -q holehe alice@example.com -
Increase timeout tolerance
# Default timeout is typically 10s; increase to 20s holehe alice@example.com --timeout 20 -
Reduce concurrency pressure — use
--only-usedto filter noise and focus on positive hits:holehe alice@example.com --only-used
Scenario 3: Persistent [x] on Specific Services
Some platforms (Instagram, LinkedIn, Facebook) implement aggressive anti-automation measures. Holehe cannot bypass these—the modules explicitly detect and report the limitation without attempting evasion.
Diagnostic command to export all results for pattern analysis:
holehe alice@example.com --csv > results.csv
Then review which services consistently rate-limit:
# Quick analysis of exported CSV
import pandas as pd
df = pd.read_csv('results.csv')
rate_limited = df[df['rateLimit'] == True]
print(rate_limited['domain'].value_counts())
Technical Architecture: Why Holehe Doesn't Retry
The TrioProgress instrument in holehe/instruments.py manages concurrent module execution with structured concurrency. The rate-limit-as-marker design aligns with this architecture:
| Design Choice | Rationale |
|---|---|
| No automatic retries | Prevents exacerbating throttling; respects service boundaries |
| Immediate result return | Preserves structured concurrency deadlines in Trio |
| User-visible flagging | Enables informed decision-making about data completeness |
| CSV export inclusion | Allows programmatic post-processing of incomplete scans |
Summary
- Rate limit detection: Each module catches HTTP 429 responses and returns
"rateLimit": Truein a standardized dictionary - Visual reporting:
holehe/core.pyrenders yellow[x]markers for throttled services without stopping the scan - Isolated throttling: No action needed—results are complete for other services
- Widespread throttling: Rotate IP addresses via VPN/proxy, increase
--timeout, or reduce query volume with--only-used - Data recovery: Export to CSV preserves rate-limit status for later targeted re-scanning
Frequently Asked Questions
Does Holehe automatically retry when rate limited?
No. When a module detects rate limiting, it returns immediately with rateLimit=True. The tool does not implement exponential backoff or retry logic, as this could violate service terms and worsen throttling conditions.
Can I increase the delay between requests to avoid rate limits?
Holehe does not expose a global delay parameter. The tool uses structured concurrency via Trio to run modules concurrently with fixed timeouts. To reduce pressure, use --timeout to allow slower responses, or run fewer modules by targeting specific services.
Why do some services always show [x] even with fresh IPs?
Major platforms deploy sophisticated bot detection (behavioral analysis, TLS fingerprinting, JavaScript challenges) that Holehe does not attempt to bypass. The [x] marker honestly reports this limitation rather than providing false negatives.
Is there a way to resume a scan that hit many rate limits?
There is no built-in resume function. However, the --csv export records all results including rateLimit=True entries. You can parse this output and manually re-run checks for specific domains after changing your network configuration.
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 →