Holehe Detection Limitations: Why This OSINT Tool Misses Accounts and How to Work Around It
Holehe cannot detect email-registered accounts when services use CAPTCHAs, JavaScript-dependent checks, rate-limiting, or change their response format, because it relies on simple HTTP requests to public "email availability" endpoints.
Holehe is a popular open-source OSINT tool by megadose that checks whether an email address is registered across 300+ services. According to the megadose/holehe source code, its detection method follows a uniform pattern: each module sends a single HTTP request mimicking a Firefox browser, then matches the raw text response against hardcoded keywords like "no" or "ok". This design creates specific Holehe detection limitations that security researchers and OSINT practitioners must understand.
How Holehe Detection Actually Works
The core detection logic lives in individual service modules. In holehe/modules/software/lastpass.py, the pattern is representative of all 300+ modules:
async def lastpass(email, client, out):
headers = {...'User-Agent': random.choice(ua["browsers"]["firefox"]),...}
params = {'check': 'avail', 'username': email}
response = await client.get('https://lastpass.com/create_account.php',
params=params, headers=headers)
if response.text == "no": # email exists
out.append({"exists": True, ...})
elif response.text in ("ok","emailinvalid"): # email not used
out.append({"exists": False, ...})
else: # rate‑limit or unknown response
out.append({"rateLimit": True, ...})
This simplicity enables speed and scalability but introduces significant constraints.
Critical Holehe Detection Limitations
Requires Static, Public Email-Availability Endpoints
Every module depends on a single HTTP GET or POST to an unauthenticated endpoint that returns plaintext responses. If a service hides its registration check behind JavaScript execution, dynamic rendering, or a JSON API requiring CSRF tokens, Holehe cannot interpret it. The holehe/modules/software/lastpass.py implementation at lines 28-34 demonstrates this: it directly compares response.text to fixed strings with no parsing layer for complex responses.
Fragile to Response Format Changes
Detection relies on exact string matching. In holehe/modules/software/lastpass.py lines 32-42, the module checks for "no" (account exists), "ok" or "emailinvalid" (account does not exist). Any wording change, added HTML wrapper, or redirect breaks detection and produces false negatives or positives.
Coarse Rate-Limit Handling
When a service returns a rate-limit response, Holehe's core orchestration in holehe/core.py lines 22-31 marks it as rateLimit: True and continues without retry logic. This means:
- Temporary IP blocks hide existing accounts
- No exponential backoff or proxy rotation occurs
- Results may incorrectly suggest an account does not exist
No Password-Recovery Path for Many Sites
The --no-password-recovery flag disables additional verification flows. According to holehe/core.py lines 55-60, several modules including Adobe and Mail.ru are deliberately excluded when this flag is set. If a service only reveals account existence through password-reset flows, Holehe misses it entirely unless the flag is omitted.
Cannot Bypass Anti-Bot Protections
Holehe does not support:
- CAPTCHA solving
- Cloudflare challenge handling
- JavaScript execution
- Browser automation
Services protecting their registration endpoints with these mechanisms return "rate-limited" or "error" statuses regardless of actual account existence.
Generic Network Error Handling
Unexpected exceptions in holehe/core.py lines 66-78 are caught and reported as "error": True without retry logic. Transient connectivity problems, DNS failures, or TLS handshake timeouts therefore hide real results rather than triggering reattempts.
Limited to Curated Module List
Holehe only knows services with Python modules under holehe/modules/*. New platforms, URL changes, or API migrations remain invisible until manually added.
Async Concurrency Timeout Constraints
Holehe uses trio for asynchronous requests, but the default 10-second timeout (--timeout 10) in holehe/core.py lines 94-96 aborts slower services prematurely.
# Increase timeout to reduce false negatives from slow endpoints
holehe user@example.com --timeout 30
When Holehe Detection Fails: Practical Examples
| Scenario | Result | Cause |
|---|---|---|
| Service adds Cloudflare to registration page | "rateLimit": true |
Cannot execute JavaScript challenge |
API response changes from "no" to "taken" |
"exists": false (incorrect) |
String match fails |
| Password-reset only reveals account | Missed detection | --no-password-recovery excludes module |
| 5-second response time | "error": true |
Default timeout too aggressive |
| CAPTCHA on email check | "rateLimit": true |
No CAPTCHA-solving integration |
Key Files Defining Detection Boundaries
holehe/core.py— Central orchestration, argument parsing, rate-limit and error handling (lines 21-31, 55-60, 66-78, 94-96)holehe/modules/*/*.py— Individual service checks implementing the simple availability request patternholehe/localuseragent.py— Random Firefox user-agent rotation for request fingerprintingholehe/instruments.py— Trio-based async progress bar and event loop implementation
Summary
Holehe's detection limitations stem from its architectural choice: fast, lightweight HTTP requests to public endpoints with plaintext response parsing. Key constraints include:
- Endpoint dependency — No JavaScript, CAPTCHA, or dynamic API support
- Fragile string matching — Response changes break detection
- No retry logic — Rate limits and network errors hide results
- Optional password-recovery — Some modules disabled by flags
- Fixed module list — New services require manual addition
- Timeout rigidity — Default 10s may abort legitimate checks
For services with straightforward email-availability endpoints, Holehe remains effective. For protected or complex authentication flows, expect false negatives.
Frequently Asked Questions
Why does Holehe report "rateLimit" when no rate limit exists?
Holehe uses "rateLimit": true as a catch-all for any non-matching response. According to holehe/core.py, this includes CAPTCHA pages, Cloudflare challenges, unexpected HTML, and actual rate-limit responses. The tool cannot distinguish between these cases because it lacks JavaScript execution and advanced response parsing.
Can Holehe detect accounts on services with JavaScript-based checks?
No. Holehe's modules in holehe/modules/* perform static HTTP requests only. Services that load registration checks dynamically or require browser interaction return "rateLimit" or "error" statuses. Browser automation tools like Selenium or Playwright are required for these cases.
How can I reduce false negatives from slow services?
Increase the timeout beyond the default 10 seconds: holehe user@example.com --timeout 30. The timeout parameter in holehe/core.py lines 94-96 controls how long trio waits for each async request. Values above 30 seconds reduce premature failures but slow overall execution.
Does disabling password-recovery checks improve accuracy?
No—it reduces coverage. The --no-password-recovery flag excludes modules like Adobe and Mail.ru that verify accounts through password-reset flows. Only use this flag when speed is prioritized over completeness, as documented in holehe/core.py lines 55-60.
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 →