Observed since 20 Oct, 19:53 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A comprehensive Python client library for the Search API with enhanced error handling and balance management
A comprehensive Python client library for the Search API with enhanced error handling, balance management, and improved data processing. Acquire your API key through @ADSearchEngine_bot on Telegram.
recovery_check, recovery_modules; retrieve available modules with get_recovery_modules()search_company(company, country=..., page=..., limit=...) returns CompanySearchResult (same shape as domain)get_usage_stats(), get_cache_stats(), get_access_logs(limit=...) with full response modelsPricingInfo.recovery_check_cost, EmailSearchResult.recovery_check (RecoveryCheckResult), RecoveryModule, RecoveryModulesResponse, UsageStatsaddresses_structured, all_names, all_dobs, related_persons, criminal_records, phone_numbers_full, censored_numbers, confirmed_numbers, other_emails, alternative_namespip install AD-SearchAPI
from search_api import SearchAPI, InsufficientBalanceError
client = SearchAPI(api_key="your_api_key")
try:
balance = client.get_balance()
print(f"Current balance: {balance}")
print(f"Cost per search: ${balance.credit_cost_per_search}")
access_logs = client.get_access_logs()
print(f"Total access log entries: {len(access_logs)}")
result = client.search_email(
"example@domain.com",
house_value=True,
extra_info=True
)
print(f"Name: {result.person.name if result.person else 'N/A'}")
print(f"Total results: {result.total_results}")
print(f"Search cost: ${result.search_cost}")
for addr in result.addresses:
print(f"Address: {addr}")
if addr.zestimate:
print(f" Zestimate: ${addr.zestimate:,.2f}")
except InsufficientBalanceError as e:
print(f"Insufficient balance: {e}")
print(f"Current: {e.current_balance}, Required: {e.required_credits}")
from search_api import SearchAPI, SearchAPIConfig
config = SearchAPIConfig(
api_key="your_api_key",
debug_mode=True, # Enable debug logging
timeout=120, # 2 minutes timeout
max_retries=5, # Retry failed requests
proxy={ # Optional proxy
"http": "http://proxy:8080",
"https": "https://proxy:8080"
}
)
client = SearchAPI(config=config)
The client provides balance checking capabilities, but does not automatically check balance before each search. You should check your balance manually when needed:
from search_api import InsufficientBalanceError
try:
balance = client.get_balance()
print(f"Balance: {balance.current_balance} {balance.currency}")
print(f"Cost per search: {balance.credit_cost_per_search}")
# Calculate required credits based on actual search costs
email_search_cost = 0.0025
phone_search_cost = 0.0025
domain_search_cost = 0.0025
required_credits = 5 * email_search_cost
if balance.current_balance < required_credits:
print(f"⚠️ Insufficient balance for {required_credits} searches")
else:
print(f"✅ Sufficient balance for {required_credits} searches")
except InsufficientBalanceError as e:
print(f"❌ Insufficient balance: {e}")
print(f" Current: {e.current_balance}")
print(f" Required: {e.required_credits}")
Retrieve access logs (optional limit), usage stats, and cache stats:
# Get access logs (optional limit, default 100, max 1000)
access_logs = client.get_access_logs(limit=50)
print(f"Total access log entries: {len(access_logs)}")
# Show recent activity
for log in access_logs[:5]:
print(f"IP: {log.ip_address}")
print(f"Last accessed: {log.last_accessed}")
print(f"Search type: {log.search_type}, Cost: {log.search_cost}")
print("---")
# Usage statistics (today and total)
stats = client.get_usage_stats()
print(f"Today: {stats.today_searches} searches, ${stats.today_cost:.4f}")
print(f"Total: {stats.total_searches} searches, ${stats.total_cost:.4f}")
# Cache statistics
cache_stats = client.get_cache_stats()
print("Cache:", cache_stats)
# Available recovery modules (for email recovery verification)
recovery = client.get_recovery_modules()
print("Recovery modules:", [m.module_name for m in recovery.modules])
print("Pricing:", recovery.pricing)
# Use in search_email(..., recovery_check=True, recovery_modules={"module_order": [...], "enabled_modules": [...]})
# Analyze access patterns
unique_ips = set(log.ip_address for log in access_logs)
print(f"Unique IP addresses: {len(unique_ips)}")
# Find most active IP
ip_counts = {}
for log in access_logs:
ip_counts[log.ip_address] = ip_counts.get(log.ip_address, 0) + 1
most_active_ip = max(ip_counts.items(), key=lambda x: x[1])
print(f"Most active IP: {most_active_ip[0]} ({most_active_ip[1]} accesses)")
result = client.search_email(
"john.doe@example.com",
house_value=True,
extra_info=True,
carrier_info=True,
tlo_enrichment=True,
recovery_check=True, # Phone Recovery Verification (email only)
recovery_modules={"module_order": ["yahoo", "outlook"], "enabled_modules": ["yahoo", "outlook"]}, # optional
phone_format="international" # or "national", "e164"
)
print(f"Email: {result.email}")
print(f"Valid: {result.email_valid}")
print(f"Type: {result.email_type}")
print(f"Search Cost: ${result.search_cost}")
# Access detailed pricing breakdown
if result.pricing:
print(f"Pricing Breakdown:")
print(f" Base Search: ${result.pricing.search_cost:.4f}")
print(f" Extra Info: ${result.pricing.extra_info_cost:.4f}")
print(f" Zestimate: ${result.pricing.zestimate_cost:.4f}")
print(f" Carrier: ${result.pricing.carrier_cost:.4f}")
print(f" TLO Enrichment: ${result.pricing.tlo_enrichment_cost:.4f}")
if result.pricing.recovery_check_cost:
print(f" Recovery Check: ${result.pricing.recovery_check_cost:.4f}")
print(f" Total Cost: ${result.pricing.total_cost:.4f}")
# Phone Recovery Verification result (when recovery_check=True)
if result.recovery_check:
print(f"Recovery matched: {result.recovery_check.matched}")
print(f"Matched number: {result.recovery_check.matched_number}")
print(f"Modules used: {result.recovery_check.modules_used}")
if result.person:
print(f"Name: {result.person.name}")
print(f"DOB: {result.person.dob}")
print(f"Age: {result.person.age}")
for addr in result.addresses:
print(f"Address: {addr}")
if addr.zestimate:
print(f" Zestimate: ${addr.zestimate:,.2f}")
for phone in result.phone_numbers:
print(f"Phone: {phone.number}")
results = client.search_phone(
"+1234567890",
house_value=True,
extra_info=True,
carrier_info=True,
tlo_enrichment=True,
phone_format="international"
)
for result in results:
print(f"Phone: {result.phone.number}")
print(f"Search Cost: ${result.search_cost}")
# Access detailed pricing breakdown
if result.pricing:
print(f" Total Cost: ${result.pricing.total_cost:.4f}")
print(f" Breakdown: {result.pricing}")
if result.person:
print(f"Name: {result.person.name}")
print(f"DOB: {result.person.dob}")
print(f"Total results: {result.total_results}")
result = client.search_domain("example.com", page=1, limit=100)
print(f"Domain: {result.domain}")
print(f"Valid: {result.domain_valid}")
print(f"Total results: {result.total_results}")
print(f"Search Cost: ${result.search_cost}")
if result.pagination:
print(f"Pagination: {result.pagination}")
for email_result in result.results:
print(f"Email: {email_result.email}")
if email_result.person:
print(f"Name: {email_result.person.name}")
# Each result can include TLO/enrichment: addresses_structured, all_names, all_dobs,
# related_persons, criminal_records, phone_numbers_full, censored_numbers, confirmed_numbers, etc.
result = client.search_company("Acme Corp", country="US", page=1, limit=100)
print(f"Company: {result.company}")
print(f"Total results: {result.total_results}")
print(f"Search Cost: ${result.search_cost}")
if result.country:
print(f"Country filter: {result.country}")
for contact in result.results:
if contact.person:
print(f"Name: {contact.person.name}")
print(f"Emails: {contact.emails}")
print(f"Phones: {[p.number for p in contact.phone_numbers]}")
# Same rich fields as domain/email: addresses_structured, related_persons, etc.
The library provides comprehensive error handling with specific exception types:
from search_api import (
SearchAPIError,
AuthenticationError,
ValidationError,
InsufficientBalanceError,
RateLimitError,
ServerError,
NetworkError,
TimeoutError,
ConfigurationError
)
try:
result = client.search_email("test@example.com")
except ValidationError as e:
print(f"Invalid input: {e}")
except InsufficientBalanceError as e:
print(f"Insufficient balance: {e}")
print(f"Current: {e.current_balance}, Required: {e.required_credits}")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
except RateLimitError as e:
print(f"Rate limit exceeded: {e}")
except ServerError as e:
print(f"Server error: {e}")
except NetworkError as e:
print(f"Network error: {e}")
except TimeoutError as e:
print(f"Request timeout: {e}")
except SearchAPIError as e:
print(f"API error: {e}")
Use the client as a context manager for automatic resource cleanup:
with SearchAPI(api_key="your_api_key") as client:
balance = client.get_balance()
result = client.search_email("test@example.com")
# Resources automatically cleaned up when exiting context
@dataclass
class Address:
street: str
city: Optional[str] = None
state: Optional[str] = None
postal_code: Optional[str] = None
country: Optional[str] = None
zestimate: Optional[Decimal] = None
zpid: Optional[str] = None
bedrooms: Optional[int] = None
bathrooms: Optional[float] = None
living_area: Optional[int] = None
home_status: Optional[str] = None
last_known_date: Optional[date] = None
@dataclass
class Person:
name: Optional[str] = None
dob: Optional[date] = None
age: Optional[int] = None
@dataclass
class PhoneNumber:
number: str
country_code: str = "US"
is_valid: bool = True
phone_type: Optional[str] = None
carrier: Optional[str] = None
@dataclass
class BalanceInfo:
current_balance: float
currency: str = "USD"
last_updated: Optional[datetime] = None
credit_cost_per_search: Optional[float] = None
@dataclass
class AccessLog:
ip_address: str
last_accessed: Optional[datetime] = None
user_agent: Optional[str] = None
endpoint: Optional[str] = None
method: Optional[str] = None
status_code: Optional[int] = None
response_time: Optional[float] = None
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key | str | Required | Your API key |
base_url | str | "https://search-api.dev/search.php" | API base URL |
max_retries | int | 1 | Maximum retry attempts |
timeout | int | 90 | Request timeout in seconds |
debug_mode | bool | False | Enable debug logging |
proxy | Dict | None | Proxy configuration |
user_agent | str | Chrome UA | Custom user agent |
See the examples/ directory for comprehensive usage examples:
Contributions are welcome! Please submit a Pull Request with your changes or open an issue for discussion.
This project is licensed under the MIT License - see the LICENSE file for details.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 2.0.5 | 22 Feb 2026 | 11 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 19:53 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:be6e489fb393bb601c00394a6783ce2005b7e4e706f653ab16decd842bceb9fd