Loading...
Loading...
HaveIBeenPwned API Documentation - Check if email accounts or passwords have been compromised in data breaches
npx skill4agent add rawveg/skillsforge-marketplace haveibeenpwnedimport requests
def check_account_breaches(email, api_key):
"""Check if an account appears in any breaches"""
headers = {
'hibp-api-key': api_key,
'user-agent': 'MyApp/1.0'
}
url = f'https://haveibeenpwned.com/api/v3/breachedaccount/{email}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json() # List of breach objects
elif response.status_code == 404:
return [] # Account not found in breaches
else:
response.raise_for_status()
# Usage
breaches = check_account_breaches('user@example.com', 'your-api-key')
print(f"Found in {len(breaches)} breaches")import hashlib
import requests
def check_password_pwned(password):
"""Check if password appears in breaches using k-anonymity"""
# Hash password with SHA-1
sha1_hash = hashlib.sha1(password.encode('utf-8')).hexdigest().upper()
prefix = sha1_hash[:5]
suffix = sha1_hash[5:]
# Query API with first 5 characters only
url = f'https://api.pwnedpasswords.com/range/{prefix}'
response = requests.get(url)
# Parse response for matching suffix
hashes = (line.split(':') for line in response.text.splitlines())
for hash_suffix, count in hashes:
if hash_suffix == suffix:
return int(count) # Times password appears in breaches
return 0 # Password not found
# Usage
count = check_password_pwned('password123')
if count > 0:
print(f"⚠️ Password found {count} times in breaches!")import requests
def get_all_breaches(domain=None):
"""Retrieve all breaches, optionally filtered by domain"""
url = 'https://haveibeenpwned.com/api/v3/breaches'
params = {'domain': domain} if domain else {}
headers = {'user-agent': 'MyApp/1.0'}
response = requests.get(url, headers=headers, params=params)
return response.json()
# Usage - no authentication required
breaches = get_all_breaches()
print(f"Total breaches: {len(breaches)}")
# Filter by domain
adobe_breaches = get_all_breaches(domain='adobe.com')import requests
import time
def monitor_latest_breach(check_interval=3600):
"""Poll for new breaches every hour"""
last_breach_name = None
while True:
url = 'https://haveibeenpwned.com/api/v3/latestbreach'
headers = {'user-agent': 'MyApp/1.0'}
response = requests.get(url, headers=headers)
if response.status_code == 200:
breach = response.json()
if breach['Name'] != last_breach_name:
print(f"🆕 New breach: {breach['Title']}")
print(f" Accounts affected: {breach['PwnCount']:,}")
last_breach_name = breach['Name']
time.sleep(check_interval)import requests
def search_domain_breaches(domain, api_key):
"""Search for all breached emails in a verified domain"""
headers = {
'hibp-api-key': api_key,
'user-agent': 'MyApp/1.0'
}
url = f'https://haveibeenpwned.com/api/v3/breacheddomain/{domain}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
results = response.json()
# Returns: {"alias1": ["Adobe"], "alias2": ["Adobe", "Gawker"]}
total_affected = len(results)
print(f"Found {total_affected} compromised accounts")
return results
else:
response.raise_for_status()import requests
def check_pastes(email, api_key):
"""Check if email appears in any pastes"""
headers = {
'hibp-api-key': api_key,
'user-agent': 'MyApp/1.0'
}
url = f'https://haveibeenpwned.com/api/v3/pasteaccount/{email}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
pastes = response.json()
for paste in pastes:
print(f"{paste['Source']}: {paste['Title']}")
print(f" Date: {paste['Date']}")
print(f" Emails found: {paste['EmailCount']}")
return pastes
elif response.status_code == 404:
return [] # No pastes foundimport hashlib
import requests
def check_password_secure(password):
"""Check password with padding to prevent inference attacks"""
sha1_hash = hashlib.sha1(password.encode('utf-8')).hexdigest().upper()
prefix = sha1_hash[:5]
suffix = sha1_hash[5:]
headers = {'Add-Padding': 'true'}
url = f'https://api.pwnedpasswords.com/range/{prefix}'
response = requests.get(url, headers=headers)
# Parse response, ignore padded entries (count=0)
for line in response.text.splitlines():
hash_suffix, count = line.split(':')
if hash_suffix == suffix and int(count) > 0:
return int(count)
return 0import requests
import time
def api_call_with_retry(url, headers, max_retries=3):
"""Make API call with automatic retry on rate limit"""
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
# Rate limited - wait and retry
retry_after = int(response.headers.get('retry-after', 2))
print(f"Rate limited, waiting {retry_after}s...")
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded")import requests
def get_subscription_info(api_key):
"""Retrieve API subscription details and limits"""
headers = {
'hibp-api-key': api_key,
'user-agent': 'MyApp/1.0'
}
url = 'https://haveibeenpwned.com/api/v3/subscription/status'
response = requests.get(url, headers=headers)
if response.status_code == 200:
info = response.json()
print(f"Plan: {info['SubscriptionName']}")
print(f"Rate limit: {info['Rpm']} requests/minute")
print(f"Valid until: {info['SubscribedUntil']}")
return infoimport requests
def check_stealer_logs(email, api_key):
"""Check if credentials appear in info stealer malware logs"""
headers = {
'hibp-api-key': api_key,
'user-agent': 'MyApp/1.0'
}
url = f'https://haveibeenpwned.com/api/v3/stealerlogsbyemail/{email}'
response = requests.get(url, headers=headers)
if response.status_code == 200:
domains = response.json() # List of website domains
print(f"Credentials found for {len(domains)} websites")
return domains
elif response.status_code == 404:
return [] # Not found in stealer logs
# Requires Pwned 5+ subscriptionhibp-api-key: {your-key}00000000000000000000000000000000retry-after| Code | Meaning |
|---|---|
| 200 | Success - data found |
| 404 | Not found (account not in breaches) |
| 401 | Unauthorized (invalid API key) |
| 403 | Forbidden (missing user-agent) |
| 429 | Rate limit exceeded |
references/view# Prevent users from choosing compromised passwords
def validate_signup_password(password):
count = check_password_pwned(password)
if count > 0:
return False, f"This password appears in {count} data breaches"
return True, "Password is secure"# Notify users when their account appears in new breach
def notify_affected_users():
latest = get_latest_breach()
affected_users = query_users_in_breach(latest['Name'])
for user in affected_users:
send_notification(user, latest)# Verify all domain accounts for compliance reporting
def domain_security_audit(domain, api_key):
breached = search_domain_breaches(domain, api_key)
report = {
'total_accounts': len(breached),
'affected_accounts': breached,
'timestamp': datetime.now()
}
return reportGET /breachedaccount/{account}GET /pasteaccount/{account}GET /breacheddomain/{domain}GET /subscribeddomainsGET /subscription/statusGET /stealerlogsbyemail/{email}GET /stealerlogsbywebsitedomain/{domain}GET /stealerlogsbyemaildomain/{domain}GET /breachesGET /breach/{name}GET /latestbreachGET /dataclassesGET https://api.pwnedpasswords.com/range/{prefix}hibp-integration-tests.comaccount-exists@multiple-breaches@spam-list-only@stealer-log@opt-out@00000000000000000000000000000000Add-Padding: true