Skip to main content

Typed Python client for the WhatsApp Data API (checkleaked.cc / RapidAPI): profile info, phone breaches, carrier lookup, Telegram, OSINT, bulk checks and a money-saving cache-first lookup.

Project description

whatsapp-data-sdk (Python)

PyPI version Python versions CI license: MIT website

Typed Python client for the WhatsApp Data API — official SDK for whatsapp.checkleaked.cc (also on RapidAPI). The Python port of whatsapp-data-sdk (npm), same endpoints and behavior.

WhatsApp profile lookups, phone breaches, carrier data, Telegram checks, OSINT, geo/business search, bulk verification — plus a cache-first lookup that reads the cheap DB endpoint before spending on a live check.

  • 🐍 Typed (TypedDict responses, py.typed), one dependency (requests).
  • 💸 Built-in cache-first strategy to minimize cost.
  • 🔁 Timeouts, retries with backoff (Retry-After aware), and a clean error taxonomy.

Install

pip install whatsapp-data-sdk

Quick start

from whatsapp_data_sdk import WhatsAppDataClient

client = WhatsAppDataClient(api_key="YOUR_KEY")  # sent as x-rapidapi-key

profile = client.get_profile("59898297150")
print(profile.get("exists"), profile.get("about"), profile.get("profilePic"))

Authentication & hosts

Your key is always sent in x-rapidapi-key. Choose where requests go with transport:

transport Live host Cache / DB-only host
"proxy" (default) whatsapp-proxy.checkleaked.cc same host, /number_cache path
"rapidapi" wp-data.p.rapidapi.com wp-data-db-only.p.rapidapi.com
client = WhatsAppDataClient(api_key="RAPIDAPI_KEY", transport="rapidapi")

Override URLs/hosts via base_url, cache_base_url, rapidapi_host, rapidapi_cache_host.

💸 Cache-first lookups (save money)

check_cached() reads the cheap cache / DB-only endpoint first and only falls back to a paid live check on a true miss.

r1 = client.check_cached("59898297150")                  # cacheFirst (default)
print(r1["_source"])                                     # "cache" | "live"
r2 = client.check_cached("59898297150", mode="cacheOnly")  # never a live call
r3 = client.check_cached("59898297150", mode="live")       # always fresh

An authoritative cached "not on WhatsApp" record counts as a hit (no wasteful live re-check); only a true NOT_IN_DATABASE miss falls through to live.

API

Every method maps 1:1 to a marketplace endpoint.

# Profile & pictures
client.get_profile(number, telegram=True, include_carrier=True)  # Get Profile Information
client.get_profile_no_picture(number)                            # (No profile pic)
pic = client.get_last_picture(number)                            # JPEG bytes -> pic.content, pic.to_data_uri()
client.get_device_count(number)                                  # Device count
client.get_osint_info(number)                                    # OSINT Info

# Breaches
client.get_phone_breaches(number, limit=50)                      # built-in (no external key)
client.get_phone_breaches_external(number, api_key="...")        # your checkleaked.cc key

# Search & database
client.search(country_code="UY", is_business=True, limit=20)     # Search
client.search_google_maps(latitude=-34.9, longitude=-56.16, radius=2000)  # Search in Google Maps
client.get_leaked_numbers_info()                                 # Leaked Numbers (500M) -> Drive link (MEGA tier)
client.download_entire_database()                                # Download the Entire DB -> Drive link (MEGA tier)

# Bulk
client.bulk_check(numbers)                                       # live (max 50)
client.bulk_check_db_basic(numbers)                              # DB basic (max 1000)
client.bulk_check_db_full(numbers)                               # DB full (max 1000)

# Telegram / carrier
client.get_telegram_profile("59898297150")                      # experimental
client.get_telegram_profile(["num1", "num2"])
client.carrier_lookup(number)                                    # Carrier Lookup
client.carrier_lookup_alt(number, page=2)                        # Carrier Lookup Alternative

"Not found" resolves — it does not raise

A number not on WhatsApp is a normal result, so these resolve (never raise):

  • get_profile / get_profile_no_picture / check_cached → a dict with exists=False (and code="NUMBER_NOT_FOUND").
  • search with zero matches → an empty page (success=False, data["docs"] == []).
  • get_device_count for a non-WhatsApp number → success=False.

What does raise: invalid number (400), auth (401/403), rate limit (429), timeout, network, 5xx.

Per-request options

Every method accepts timeout (seconds) and retries:

client.get_profile("59898297150", timeout=5, retries=0)

Errors

All failures raise a subclass of WhatsAppDataError:

Class When
ValidationError Bad arguments (raised before any request; no .status).
AuthError 401 / 403 — missing/invalid/unsubscribed key.
RateLimitError 429 — carries .retry_after_ms when the server sent Retry-After.
HttpError Any other non-2xx (e.g. 400, 5xx); has .status, .body.
TimeoutError Request exceeded the timeout.
NetworkError Transport failure.
WhatsAppDataError Base class.
from whatsapp_data_sdk import AuthError, RateLimitError, WhatsAppDataError

try:
    client.get_profile("59898297150")
except AuthError:
    ...  # 401/403
except RateLimitError as e:
    print(e.retry_after_ms)
except WhatsAppDataError as e:
    print(e.status, e.body)

POSTs (bulk_check, bulk_check_db_*) are not auto-retried, to avoid double-spending quota.

Phone number formats

Any format works — the SDK normalizes; the helpers are exported:

from whatsapp_data_sdk import to_digits, to_e164
to_digits("+598 98 297 150")  # "59898297150"  (path & live endpoints)
to_e164("59898297150")        # "+59898297150" (bulk-DB endpoints require it)

Notes

Enrichments run entirely server-side — you never supply Gemini, LeakCheck, or any other keys. Face analysis, breach lookups, etc. are handled by the API. The only user-provided key is your own checkleaked.cc key for get_phone_breaches_external.

License

MIT © Eduardo Airaudo

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

whatsapp_data_sdk-1.0.0.tar.gz (14.9 kB view details)

Uploaded Source

Built Distribution

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

whatsapp_data_sdk-1.0.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file whatsapp_data_sdk-1.0.0.tar.gz.

File metadata

  • Download URL: whatsapp_data_sdk-1.0.0.tar.gz
  • Upload date:
  • Size: 14.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for whatsapp_data_sdk-1.0.0.tar.gz
Algorithm Hash digest
SHA256 bed899f84f784cc561c8a5fd107ce422c4ff420af03e5600340cab7a05d77ba0
MD5 0dd0a9cb39c25ab5b3315b7ef40c366a
BLAKE2b-256 601009e2bd81bfa8cfac01b698cb58584e0461fd6604b290296918a401c13d11

See more details on using hashes here.

Provenance

The following attestation bundles were made for whatsapp_data_sdk-1.0.0.tar.gz:

Publisher: publish.yml on eduair94/whatsapp-data-sdk-python

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

File details

Details for the file whatsapp_data_sdk-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for whatsapp_data_sdk-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b44a37a0fc4745c5b1cbf587ec8429875b6ac5c128b50ec622bfbcaffd96879
MD5 8d1d6384ea1dff447aacc32aac506301
BLAKE2b-256 1f44bafaefe848cdba2e56ff4637cd3c9cf7ec02eb0e55b0c6a6a07a5c1e01c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for whatsapp_data_sdk-1.0.0-py3-none-any.whl:

Publisher: publish.yml on eduair94/whatsapp-data-sdk-python

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