Skip to main content

Python client library for the Have I Been Pwned API

Project description

Have I Been Pwned - Python Library

PyPI version Python Support License: MIT

A comprehensive, easy-to-use Python library for the Have I Been Pwned API v3. Check if email accounts have been compromised in data breaches, validate password security, and access paste and stealer log data - all through a clean, Pythonic interface.

โœจ Features

  • ๐Ÿ” Pwned Passwords: Check passwords using k-Anonymity (no API key needed)
  • ๐Ÿ“ง Breach Data: Search breached accounts and get detailed breach information
  • ๐Ÿ“‹ Pastes: Find paste exposures for email addresses
  • ๐ŸŽฏ Stealer Logs: Access malware-captured credentials (Pwned 5+ subscription)
  • ๐Ÿข Domain Search: Search breaches across verified domains
  • ๐Ÿ›ก๏ธ Type Safety: Full type hints for better IDE support and code quality
  • โšก Error Handling: Comprehensive exception hierarchy for robust error management
  • ๐Ÿšฆ Rate Limiting: Automatic handling of API rate limits

๐Ÿ“š Documentation

๐Ÿš€ Quick Start

Installation

pip install haveibeenpwned-py

Full installation instructions โ†’

Simple Example

from haveibeenpwned import HIBP

# Check if an account has been breached (requires API key)
hibp = HIBP(api_key="your-api-key-here")
breaches = hibp.get_account_breaches("test@example.com")
for breach in breaches:
    print(f"๐Ÿšจ {breach.name}: {breach.pwn_count:,} accounts affected")

# Check if a password has been pwned (no API key required!)
hibp_passwords = HIBP()
count = hibp_passwords.is_password_pwned("password123")
if count > 0:
    print(f"โš ๏ธ  Password found in {count:,} breaches!")
else:
    print("โœ“ Password not found in any breaches")

More examples and detailed usage โ†’

๐Ÿ“– API Endpoints

This library provides complete coverage of all HIBP API v3 endpoints:

Breaches API (7 endpoints)

  • โœ… Check account breaches
  • โœ… Get all breaches
  • โœ… Get single breach details
  • โœ… Get latest breach
  • โœ… Get data classes
  • โœ… Get domain breaches (requires verification)
  • โœ… Get subscribed domains

Pastes API

  • โœ… Get pastes for an account

Stealer Logs API (Pwned 5+ subscription)

  • โœ… Get stealer logs by email
  • โœ… Get stealer logs by website
  • โœ… Get stealer logs by email domain

Subscription API

  • โœ… Get subscription status

Pwned Passwords API (no API key required)

  • โœ… Check password by plaintext
  • โœ… Search by hash prefix (k-Anonymity)
  • โœ… SHA-1 and NTLM hash support

๐Ÿ”‘ API Key

Most endpoints require an API key from Have I Been Pwned. The Pwned Passwords API does not require authentication.

Get your API key: https://haveibeenpwned.com/API/Key

Test API key for development: 00000000000000000000000000000000

Learn more about API key setup โ†’

๐Ÿ—๏ธ Project Structure

haveibeenpwned/
โ”œโ”€โ”€ haveibeenpwned/          # Main package
โ”‚   โ”œโ”€โ”€ api.py               # Main HIBP interface
โ”‚   โ”œโ”€โ”€ breach.py            # Breach endpoints
โ”‚   โ”œโ”€โ”€ client.py            # HTTP client
โ”‚   โ”œโ”€โ”€ exceptions.py        # Custom exceptions
โ”‚   โ”œโ”€โ”€ models.py            # Data models
โ”‚   โ”œโ”€โ”€ passwords.py         # Pwned Passwords API
โ”‚   โ”œโ”€โ”€ pastes.py            # Pastes endpoints
โ”‚   โ”œโ”€โ”€ stealer_logs.py      # Stealer logs endpoints
โ”‚   โ””โ”€โ”€ subscription.py      # Subscription endpoints
โ”œโ”€โ”€ tests/                   # Comprehensive test suite
โ”œโ”€โ”€ docs/                    # Documentation
โ”‚   โ”œโ”€โ”€ INSTALL.md           # Installation guide
โ”‚   โ”œโ”€โ”€ USAGE.md             # Usage guide
โ”‚   โ”œโ”€โ”€ CONTRIBUTING.md      # Contributing guide
โ”‚   โ””โ”€โ”€ DEVELOPMENT.md       # Development guide
โ””โ”€โ”€ README.md                # This file

๐Ÿค Contributing

Contributions are welcome! This project maintains high standards:

  • โœ… Test Coverage: >95% required
  • โœ… Type Hints: Full type annotations
  • โœ… Documentation: Comprehensive docs and examples
  • โœ… Code Quality: Follows PEP 8 and best practices

Read the contributing guide โ†’

๐Ÿงช Testing

# Run all tests
./run_tests.sh all

# Run unit tests only (fast, no API key needed)
./run_tests.sh unit

# Run integration tests (requires HIBP_API_KEY)
export HIBP_API_KEY="your-api-key"
./run_tests.sh live

# Check coverage
./run_tests.sh coverage

Learn more about testing โ†’

๐Ÿ“‹ Requirements

  • Python 3.8 or higher
  • requests >= 2.25.0

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ™ Attribution

This library uses the Have I Been Pwned API. When using this library, you must provide clear attribution to Have I Been Pwned as required by their Terms of Service.

The breach and paste data is licensed under Creative Commons Attribution 4.0 International License.

โš ๏ธ Disclaimer

This is an unofficial library and is not affiliated with Troy Hunt or Have I Been Pwned. Use responsibly and in accordance with the HIBP Acceptable Use Policy.

๐Ÿ”— Resources


Made with โค๏ธ for security and privacy

Usage Examples

Breaches

Check Account Breaches

# Get all breaches for an account
breaches = hibp.get_account_breaches("test@example.com")

# Get full breach details (not truncated)
breaches = hibp.get_account_breaches(
    "test@example.com",
    truncate_response=False
)

# Filter by domain
breaches = hibp.get_account_breaches(
    "test@example.com",
    domain="adobe.com"
)

# Exclude unverified breaches
breaches = hibp.get_account_breaches(
    "test@example.com",
    include_unverified=False
)

Get All Breaches

# Get all breaches in the system
all_breaches = hibp.get_all_breaches()

# Filter by domain
adobe_breaches = hibp.get_all_breaches(domain="adobe.com")

# Get only spam lists
spam_lists = hibp.get_all_breaches(is_spam_list=True)

Get Single Breach

# Get details for a specific breach
breach = hibp.get_breach("Adobe")
print(f"Name: {breach.name}")
print(f"Date: {breach.breach_date}")
print(f"Accounts: {breach.pwn_count}")
print(f"Data classes: {', '.join(breach.data_classes)}")

Get Latest Breach

# Get the most recently added breach
latest = hibp.get_latest_breach()
print(f"Latest breach: {latest.name} added on {latest.added_date}")

Get Data Classes

# Get all data classes
data_classes = hibp.get_data_classes()
print("Available data classes:", data_classes)

Domain Search

# Get breached accounts for your verified domain
domain_breaches = hibp.get_domain_breaches("example.com")
for alias, breach_names in domain_breaches.items():
    print(f"{alias}@example.com: {', '.join(breach_names)}")

# Get your subscribed domains
domains = hibp.get_subscribed_domains()
for domain in domains:
    print(f"{domain.domain_name}: {domain.pwn_count} breached accounts")

Pastes

# Get pastes for an account
pastes = hibp.get_account_pastes("test@example.com")
for paste in pastes:
    print(f"Source: {paste.source}")
    print(f"ID: {paste.id}")
    print(f"Date: {paste.date}")
    print(f"Emails: {paste.email_count}")

Stealer Logs

Requires Pwned 5+ subscription.

# Get stealer log domains for an email
domains = hibp.get_stealer_logs_by_email("test@example.com")
print(f"Credentials captured on: {', '.join(domains)}")

# Get email addresses captured on a website
emails = hibp.get_stealer_logs_by_website("netflix.com")
print(f"Compromised accounts: {', '.join(emails)}")

# Get stealer logs by email domain
logs = hibp.get_stealer_logs_by_email_domain("example.com")
for alias, websites in logs.items():
    print(f"{alias}@example.com compromised on: {', '.join(websites)}")

Pwned Passwords

No API key required for Pwned Passwords!

# Simple password check
count = hibp.is_password_pwned("password123")
if count > 0:
    print(f"โš ๏ธ  Password found {count} times in breaches!")
else:
    print("โœ“ Password not found in breaches")

# Use NTLM hash instead of SHA-1
count = hibp.is_password_pwned("password123", use_ntlm=True)

# Add padding for enhanced privacy
count = hibp.is_password_pwned("password123", add_padding=True)

# Search by hash prefix directly
results = hibp.search_password_hashes("21BD1")  # First 5 chars of SHA-1 hash
for suffix, count in results.items():
    print(f"Hash suffix {suffix}: seen {count} times")

Subscription Status

# Get your subscription details
subscription = hibp.get_subscription_status()
print(f"Plan: {subscription.subscription_name}")
print(f"Rate limit: {subscription.rpm} requests per minute")
print(f"Max domain size: {subscription.domain_search_max_breached_accounts}")
print(f"Includes stealer logs: {subscription.includes_stealer_logs}")
print(f"Valid until: {subscription.subscribed_until}")

Advanced Usage

Using Individual API Modules

You can also access the API modules directly for more control:

from haveibeenpwned import HIBP

hibp = HIBP(api_key="your-api-key")

# Access individual API modules
breaches = hibp.breaches.get_breaches_for_account("test@example.com")
pastes = hibp.pastes.get_pastes_for_account("test@example.com")
status = hibp.subscription.get_status()
count = hibp.passwords.check_password("password123")

Custom User Agent

hibp = HIBP(
    api_key="your-api-key",
    user_agent="MyApp/1.0 (contact@example.com)"
)

Custom Timeout

hibp = HIBP(
    api_key="your-api-key",
    timeout=60  # 60 seconds
)

Error Handling

The library provides detailed exceptions for different error scenarios:

from haveibeenpwned import (
    HIBP,
    NotFoundError,
    RateLimitError,
    AuthenticationError,
    BadRequestError,
    ForbiddenError,
    ServiceUnavailableError,
    HIBPError,
)

hibp = HIBP(api_key="your-api-key")

try:
    breaches = hibp.get_account_breaches("test@example.com")
except NotFoundError:
    print("Account not found in any breaches")
except RateLimitError as e:
    print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
except AuthenticationError:
    print("Invalid API key")
except BadRequestError as e:
    print(f"Bad request: {e}")
except ForbiddenError:
    print("Access forbidden - check user agent")
except ServiceUnavailableError:
    print("Service temporarily unavailable")
except HIBPError as e:
    print(f"API error: {e}")

Models

The library provides typed models for API responses:

Breach

breach = hibp.get_breach("Adobe")

# Access breach properties
breach.name                  # "Adobe"
breach.title                 # "Adobe"
breach.domain                # "adobe.com"
breach.breach_date           # "2013-10-04"
breach.added_date            # "2013-12-04T00:00:00Z"
breach.modified_date         # "2022-05-15T23:52:49Z"
breach.pwn_count             # 152445165
breach.description           # HTML description
breach.data_classes          # ["Email addresses", "Passwords", ...]
breach.is_verified           # True
breach.is_sensitive          # False
breach.is_retired            # False
breach.is_spam_list          # False
breach.logo_path             # "Adobe.png"

# Convert to dictionary
breach_dict = breach.to_dict()

Paste

paste = pastes[0]

paste.source                 # "Pastebin"
paste.id                     # "8Q0BvKD8"
paste.title                  # "syslog"
paste.date                   # "2014-03-04T19:14:54Z"
paste.email_count            # 139

Subscription

subscription = hibp.get_subscription_status()

subscription.subscription_name                # "Pwned 1"
subscription.description                      # "Up to 10 passwords per minute..."
subscription.subscribed_until                 # "2024-12-31T23:59:59Z"
subscription.rpm                              # 10
subscription.domain_search_max_breached_accounts  # 100
subscription.includes_stealer_logs            # False

Rate Limiting

The API enforces rate limits based on your subscription level. When rate limited:

from haveibeenpwned import RateLimitError

try:
    breaches = hibp.get_account_breaches("test@example.com")
except RateLimitError as e:
    # Wait for the specified time
    import time
    time.sleep(e.retry_after)
    # Retry the request
    breaches = hibp.get_account_breaches("test@example.com")

API Key

Most endpoints require an API key. You can obtain one from: https://haveibeenpwned.com/API/Key

The Pwned Passwords API does not require an API key.

Test API Key

For testing, you can use the test API key 00000000000000000000000000000000 with test accounts:

hibp = HIBP(api_key="00000000000000000000000000000000")

# These test accounts work with the test key
breaches = hibp.get_account_breaches("account-exists@hibp-integration-tests.com")
breaches = hibp.get_account_breaches("spam-list-only@hibp-integration-tests.com")
breaches = hibp.get_account_breaches("stealer-log@hibp-integration-tests.com")

Requirements

  • Python 3.8+
  • requests >= 2.25.0

License

This project is licensed under the MIT License.

Attribution

This library uses the Have I Been Pwned API. The breach and paste data is licensed under Creative Commons Attribution 4.0 International License. When using this library, you must provide clear attribution to Have I Been Pwned.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Testing

The library includes a comprehensive test suite with both unit tests (mocked) and integration tests (live API).

Running Tests

# Install test dependencies
pip install -r requirements-test.txt

# Run all tests
pytest

# Run only unit tests (no API key needed)
pytest -m unit

# Run only integration tests (requires HIBP_API_KEY)
export HIBP_API_KEY="your-api-key"
pytest -m integration

# Run with coverage
pytest --cov=haveibeenpwned --cov-report=html

Test Coverage

The test suite includes:

  • โœ… Client & HTTP: Request handling, error responses, timeouts
  • โœ… Models: Breach, Paste, Subscription, SubscribedDomain
  • โœ… Breaches API: All 7 endpoints with full parameter testing
  • โœ… Pwned Passwords: SHA-1, NTLM, padding, k-Anonymity
  • โœ… Pastes API: Account paste retrieval
  • โœ… Stealer Logs API: Email, website, and domain searches
  • โœ… Subscription API: Status retrieval
  • โœ… Main Interface: All convenience methods

Target coverage: 90%+

Publishing & Releases

This package uses GitHub Actions for automated publishing to PyPI via Trusted Publishing.

For Maintainers: Making a Release

Once PyPI Trusted Publishing is configured, releases are simple:

# Using the release script (recommended)
./release.sh 1.0.1

# Or manually:
# 1. Update version in setup.py
# 2. Commit: git commit -am "Bump version to 1.0.1"
# 3. Tag: git tag -a v1.0.1 -m "Release 1.0.1"
# 4. Push: git push origin main --tags
# 5. Create GitHub release (triggers auto-publish to PyPI)

The GitHub Actions workflow will automatically:

  • โœ… Build the package
  • โœ… Run tests
  • โœ… Publish to PyPI (with required approval via the pypi environment)

First-Time PyPI Setup

For the initial release, PyPI Trusted Publishing must be configured:

  1. Create PyPI account (if needed):

  2. Set up Trusted Publishing:

  3. Configure GitHub Environment Protection:

    • Go to your GitHub repo โ†’ Settings โ†’ Environments
    • Create environment: pypi
    • Add required reviewers (for approval before publishing)
    • Save protection rules
  4. Make your first release:

    ./release.sh 1.0.0
    

Version Numbering

Follow Semantic Versioning:

  • MAJOR (1.0.0 โ†’ 2.0.0): Breaking changes
  • MINOR (1.0.0 โ†’ 1.1.0): New features, backward compatible
  • PATCH (1.0.0 โ†’ 1.0.1): Bug fixes, backward compatible

Release Checklist

Before releasing:

  • All tests pass: ./run_tests.sh all
  • Coverage is >90%: ./run_tests.sh coverage
  • README.md is up-to-date
  • Version number updated in setup.py
  • CHANGELOG or release notes prepared
  • No uncommitted changes

Target coverage: 90%+

API Reference

Complete Endpoint Coverage

Breaches (7 endpoints)

  • get_account_breaches(account) - Get all breaches for an account
  • get_all_breaches() - Get all breaches in the system
  • get_breach(name) - Get a single breach by name
  • get_latest_breach() - Get the most recently added breach
  • get_data_classes() - Get all data classes
  • get_domain_breaches(domain) - Get breached emails for a domain
  • get_subscribed_domains() - Get all subscribed domains

Pastes (1 endpoint)

  • get_account_pastes(account) - Get all pastes for an account

Stealer Logs (3 endpoints)

  • get_stealer_logs_by_email(email) - Get domains by email
  • get_stealer_logs_by_website(domain) - Get emails by website domain
  • get_stealer_logs_by_email_domain(domain) - Get aliases by email domain

Subscription (1 endpoint)

  • get_subscription_status() - Get subscription details

Pwned Passwords (no API key required)

  • is_password_pwned(password) - Check if password is compromised
  • search_password_hashes(prefix) - Search by hash prefix

API Key

Most endpoints require an API key. You can obtain one from: https://haveibeenpwned.com/API/Key

The Pwned Passwords API does not require an API key.

Test API Key

For testing, you can use the test API key 00000000000000000000000000000000 with test accounts:

hibp = HIBP(api_key="00000000000000000000000000000000")

# These test accounts work with the test key
breaches = hibp.get_account_breaches("account-exists@hibp-integration-tests.com")
breaches = hibp.get_account_breaches("spam-list-only@hibp-integration-tests.com")
breaches = hibp.get_account_breaches("stealer-log@hibp-integration-tests.com")

Rate Limiting

The API enforces rate limits based on your subscription level. When rate limited:

from haveibeenpwned import RateLimitError

try:
    breaches = hibp.get_account_breaches("test@example.com")
except RateLimitError as e:
    # Wait for the specified time
    import time
    time.sleep(e.retry_after)
    # Retry the request
    breaches = hibp.get_account_breaches("test@example.com")

Contributing

Contributions are welcome! Please ensure your contributions meet the following requirements:

Code Quality Standards

  • All tests must pass: Run ./run_tests.sh all to verify all tests pass
  • Code coverage must be >95%: Run ./run_tests.sh coverage to check coverage
  • Follow existing code style: Match the formatting and patterns used in the codebase
  • Add tests for new features: Both unit tests (mocked) and integration tests (live API calls where appropriate)
  • Update documentation: Keep README.md and docstrings up to date

Testing Your Changes

Before submitting a pull request:

# Run all tests
./run_tests.sh all

# Check coverage (must be >95%)
./run_tests.sh coverage

# Run unit tests only (fast, no API key needed)
./run_tests.sh unit

# Run live integration tests (requires HIBP_API_KEY)
export HIBP_API_KEY="your-api-key-here"
./run_tests.sh live

Submitting Changes

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-new-feature)
  3. Make your changes with appropriate tests
  4. Ensure all tests pass and coverage is >95%
  5. Commit your changes (git commit -am 'Add new feature')
  6. Push to the branch (git push origin feature/my-new-feature)
  7. Create a Pull Request

Disclaimer

This is an unofficial library and is not affiliated with Troy Hunt or Have I Been Pwned. Use responsibly and in accordance with the HIBP Acceptable Use Policy.

Resources

Project Structure

hibp/
โ”œโ”€โ”€ hibp/                    # Main package
โ”‚   โ”œโ”€โ”€ __init__.py          # Package exports
โ”‚   โ”œโ”€โ”€ api.py               # Main HIBP interface
โ”‚   โ”œโ”€โ”€ breach.py            # Breach endpoints
โ”‚   โ”œโ”€โ”€ client.py            # HTTP client
โ”‚   โ”œโ”€โ”€ exceptions.py        # Custom exceptions
โ”‚   โ”œโ”€โ”€ models.py            # Data models
โ”‚   โ”œโ”€โ”€ passwords.py         # Pwned Passwords API
โ”‚   โ”œโ”€โ”€ pastes.py            # Pastes endpoints
โ”‚   โ”œโ”€โ”€ stealer_logs.py      # Stealer logs endpoints
โ”‚   โ””โ”€โ”€ subscription.py      # Subscription endpoints
โ”œโ”€โ”€ tests/                   # Test suite
โ”‚   โ”œโ”€โ”€ conftest.py
โ”‚   โ”œโ”€โ”€ test_api.py
โ”‚   โ”œโ”€โ”€ test_breach.py
โ”‚   โ”œโ”€โ”€ test_client.py
โ”‚   โ”œโ”€โ”€ test_models.py
โ”‚   โ”œโ”€โ”€ test_other_endpoints.py
โ”‚   โ””โ”€โ”€ test_passwords.py
โ”œโ”€โ”€ .github/
โ”‚   โ”œโ”€โ”€ workflows/
โ”‚   โ”‚   โ”œโ”€โ”€ tests.yml              # Automated testing
โ”‚   โ”‚   โ”œโ”€โ”€ publish.yml            # PyPI publishing
โ”‚   โ”‚   โ”œโ”€โ”€ security.yml           # Security scanning
โ”‚   โ”‚   โ””โ”€โ”€ dependency-updates.yml # Dependency monitoring
โ”‚   โ””โ”€โ”€ dependabot.yml             # Automated dependency updates
โ”œโ”€โ”€ setup.py                 # Package setup
โ”œโ”€โ”€ requirements.txt         # Dependencies
โ”œโ”€โ”€ release.sh               # Automated release script
โ”œโ”€โ”€ run_tests.sh             # Test runner
โ””โ”€โ”€ README.md                # This file

Made with โค๏ธ for security and privacy

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

haveibeenpwned_py-1.0.2.tar.gz (49.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

haveibeenpwned_py-1.0.2-py3-none-any.whl (35.0 kB view details)

Uploaded Python 3

File details

Details for the file haveibeenpwned_py-1.0.2.tar.gz.

File metadata

  • Download URL: haveibeenpwned_py-1.0.2.tar.gz
  • Upload date:
  • Size: 49.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for haveibeenpwned_py-1.0.2.tar.gz
Algorithm Hash digest
SHA256 6756579e7326e13e56988116255b819c5b3d4738f62abe8c0e673b90177dd1f0
MD5 20a059fbb01f600be8bf3132b956f884
BLAKE2b-256 322d45141e43cc15dd65cf0325f8abf139c87bfe1d2eac44f464f42bda0f3201

See more details on using hashes here.

Provenance

The following attestation bundles were made for haveibeenpwned_py-1.0.2.tar.gz:

Publisher: publish.yml on dynacylabs/haveibeenpwned-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file haveibeenpwned_py-1.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for haveibeenpwned_py-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 cc29319bf6c35aa76025cee853f3b958d3efd18e856ddaf0c7b7a8343a241b1f
MD5 9ed0410e331e638226ca65ccd0c15c53
BLAKE2b-256 3dc9cf61ed26c74be8a6c7fa5bfe79c387d6bf67825e8e6ced0b8e979a6c9d21

See more details on using hashes here.

Provenance

The following attestation bundles were made for haveibeenpwned_py-1.0.2-py3-none-any.whl:

Publisher: publish.yml on dynacylabs/haveibeenpwned-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page