How the Timeout Parameter Affects Module Execution in Holehe
The --timeout flag sets a global ceiling on all HTTP requests, but individual modules can override it with shorter per-request timeouts to balance scan speed against detection accuracy.
Holehe is an open-source OSINT tool that checks email addresses across hundreds of services. When you run a scan, the timeout parameter governs how long the tool waits for network responses—directly impacting both execution time and result reliability. Understanding how this value propagates through the codebase helps you tune scans for your specific network conditions.
Where the Timeout Is Defined and Applied
The timeout journey begins in holehe/core.py, where the CLI argument is parsed and the shared HTTP client is instantiated.
CLI Argument Parsing
In holehe/core.py at lines 194-199, Holehe registers the -T / --timeout flag:
# holehe/core.py#L194-L199
parser.add_argument(
"-T", "--timeout",
type=int,
default=10,
help="Timeout for each request (default: 10)"
)
The default value of 10 seconds provides a middle ground for most internet connections.
Global Client Creation
At lines 212-214, this value is passed to httpx.AsyncClient:
# holehe/core.py#L212-L214
async with httpx.AsyncClient(timeout=args.timeout) as client:
# client is now shared across all modules
await launch_module(client, ...)
This single client object is reused for every module in the scan. Because httpx.AsyncClient accepts a timeout parameter at construction time, all requests made through this client inherit this global timeout unless explicitly overridden.
How Modules Interact With the Global Timeout
Module execution follows a simple inheritance pattern: no explicit timeout means the global value applies.
Default Behavior: Inheriting the Global Timeout
Most modules call client.get() or client.post() without specifying a timeout:
# Typical module pattern (no timeout override)
r = await client.get(f"https://api.example.com/user/{email}")
These requests automatically use the 10-second default (or whatever value you passed via -T).
Per-Request Overrides in Specific Modules
Some modules define their own shorter timeouts based on known service characteristics. These local values supersede the global client timeout:
| Module | File Path | Timeout Override | Rationale |
|---|---|---|---|
| MySpace | holehe/modules/social_media/myspace.py#L21 |
2 seconds | Fast API, quick failure acceptable |
| CaringBridge | holehe/modules/medical/caringbridge.py#L36 |
3 seconds | Medical service with rate limits |
| OnlineSequencer | holehe/modules/forum/onlinesequencer.py#L23 |
1 second | Forum with known quick responses |
| Cracked.to | holehe/modules/forum/cracked_to.py |
1 second | Forum with aggressive blocking |
Example from myspace.py:
# holehe/modules/social_media/myspace.py#L21
r = await client.get(
f"https://myspace.com/{username}",
timeout=2 # Overrides global timeout
)
This design allows service-specific tuning: slow or unreliable sites get more time, while fast, unstable ones fail quickly to keep the scan moving.
Impact on Execution and Reliability
The timeout parameter creates a direct trade-off between speed and completeness.
Higher Timeout Values (e.g., 30 seconds)
- Execution time: Increases proportionally; slow services get more chances to respond
- Accuracy: Reduces false negatives from prematurely abandoned requests
- Resource cost: More concurrent connections held open, higher memory usage
Use this when scanning from slow networks or targeting services known for latency.
Lower Timeout Values (e.g., 2-5 seconds)
- Execution time: Faster overall completion, especially with many modules
- Accuracy: Risk of missing valid accounts on slower endpoints
- Resource cost: Minimal connection holding, lower footprint
Use this for quick reconnaissance or when you prioritize speed over thoroughness.
Default Timeout (10 seconds)
The built-in default balances these factors for typical internet conditions and most public services.
Error Handling and Scan Resilience
When a timeout occurs, httpx raises a TimeoutException. Holehe modules catch this via generic exception handling:
# Pattern found across modules
try:
r = await client.get(url)
except Exception:
# Includes TimeoutException, connection errors, etc.
return {"exists": False, ...} # Site marked as not found
This architecture ensures that a single hung request cannot crash the entire scan. The exception is swallowed, the module returns a negative result, and execution continues to the next service.
Practical Usage Examples
Command-Line Examples
# Default 10-second timeout
holehe -e target@example.com
# Increase to 30 seconds for unreliable networks
holehe -e target@example.com -T 30
# Aggressive 5-second scan (may miss slow services)
holehe -e target@example.com -T 5
Programmatic Pattern (Illustrative)
While Holehe is primarily CLI-driven, the timeout flow works as follows:
import httpx
# Global client with custom timeout
client = httpx.AsyncClient(timeout=20)
# This request uses 20 seconds
await client.get("https://slow-site.com/api")
# This request overrides to 2 seconds
await client.get("https://fast-site.com/api", timeout=2)
Summary
- The
--timeoutflag sets a global ceiling for all HTTP requests viahttpx.AsyncClientinholehe/core.py - Individual modules can override this value with shorter per-request timeouts
- Higher values improve accuracy at the cost of speed and resources; lower values do the opposite
- Timeout errors are gracefully handled per-module, preventing scan crashes
- The default 10 seconds suits most use cases, but adjust based on network conditions and target service reliability
Frequently Asked Questions
What happens if I set timeout to 0 or a negative value?
Holehe does not validate against zero or negative timeouts at the CLI level. Passing 0 to httpx.AsyncClient typically disables the timeout entirely (unlimited wait), while negative values may raise an error from the underlying library. Stick to positive integers for predictable behavior.
Why do some modules ignore my custom timeout flag?
They don't ignore it—they override it. When a module passes timeout= directly to client.get() or client.post(), that value takes precedence. This is intentional: module authors tune based on observed service behavior. Your global timeout still applies to modules without explicit overrides.
Can I disable timeouts completely?
Not through official CLI options. You would need to modify holehe/core.py to pass timeout=None to the httpx.AsyncClient constructor. This removes all timing constraints but risks indefinite hangs on unresponsive services.
Does timeout affect DNS resolution or just the HTTP request?
The timeout value passed to httpx.AsyncClient governs the entire request lifecycle, including connection establishment, sending headers, and reading the response body. DNS resolution timing depends on your system's resolver and is not separately configurable within Holehe's timeout parameter.
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 →