Skip to main content

Official zero-dependency Python 3.10+ SDK for the Check-Host.cc API. Distributed network diagnostics (ping, MTR, DNS, HTTP, TCP, UDP, WHOIS) from 60+ global locations.

Project description

check-host-api

A lightweight, zero-dependency Python 3.10+ SDK for the Check-Host.cc API.

Distributed network diagnostics from 60+ global locations: ICMP ping, MTR, DNS, HTTP, TCP, UDP, WHOIS and geolocation, with the same fluent surface as the official nodejs-lib, php-lib, go-lib and CheckHost4J — plus a few extras specific to Python.

Full API reference: https://check-host.cc/docs.

Highlights

  • Zero runtime dependencies — built on top of urllib.request.
  • Full Swagger 2.0.0 parity — every endpoint covered, including /myinfo, /report/{uuid}/og-image and /report/{uuid}/country-map.
  • Type hints throughout with a PEP 561 py.typed marker.
  • POST-based requests — no URL-encoding pitfalls.
  • Built-in polling helper wait_for_report() so you don't have to babysit the report endpoint by hand.
  • Automatic API-key injection from the constructor or the CHECK_HOST_API_KEY environment variable.
  • Granular exception hierarchy — separate classes for 400, 404, 429 and 5xx.
  • Client-side validation for ports, DNS record types, MTR repeats etc.
  • OG-Image and country-map fetch + save helpers for status maps.
  • Region / DNS-type / MTR-protocol constants for IDE autocompletion.
  • Context-manager support (with CheckHost() as ch: ...).

Installation

pip install check-host-api

Requires Python 3.10+. No further dependencies.

Quickstart

from checkhost import CheckHost
from checkhost.regions import Continent, DNSType

with CheckHost() as ch:
    # Geolocation / ASN
    info = ch.info("check-host.cc")
    print(f"{info.ip} -> {info.city}, {info.country}  ({info.asn.get('name')})")

    # Ping check across Europe + North America, 3 packets per node
    task = ch.ping(
        "1.1.1.1",
        region=[Continent.EUROPE, Continent.NORTH_AMERICA],
        repeat_checks=3,
    )
    print(f"Task UUID: {task.uuid}")

    # Block until every node reports (or 20s elapses)
    report = ch.wait_for_report(task.uuid, max_wait=20.0)
    print(f"{len(report.completed_nodes)} nodes reported")

    # Save the dynamic status map (PNG, 1200x630) and country world map
    ch.save_og_image(task.uuid, "./status.png")
    ch.save_country_map(task.uuid, "./status.svg")

Authentication

The API works without a key (subject to public rate limits). For higher limits, provide an API key (UUID) via constructor or environment variable:

ch = CheckHost("YOUR_API_KEY_UUID")
# or
import os
os.environ["CHECK_HOST_API_KEY"] = "YOUR_API_KEY_UUID"
ch = CheckHost()

When both are present, the constructor argument wins.

Complete API Reference & Examples

This SDK supports both minimal invocations and detailed, options-rich requests for every endpoint.

Common Options

  • region: list of node names, ISO country codes, or continent codes (EU, NA, SA, AS, AF, OC). Continents cannot be mixed with specific node names.
  • repeat_checks: number of repeated probes per node. 0 = single shot; >= 10 enables Live Mode (continuous probing for ~repeat_checks seconds).
  • timeout: per-request connection timeout in seconds (currently a no-op on the Check-Host backend, but accepted for forward compatibility).

Information & Utilities

Get my IP

Returns the requesting client's public IPv4 / IPv6 address.

ip = ch.myip()

Get my info

Geolocation + ASN + privacy / abuse / company data for the caller's IP. Subject to bot-detection — repeated calls may yield a captcha URL in a CheckHostRateLimitError.response.

info = ch.myinfo()
print(info.country_code, info.city, info.asn.get("name"))

List monitoring nodes

locations = ch.locations()
# locations["locationlist"] is a list of nodes, each with continent,
# countryCode, isp, locationname, sponsor, etc.

Host info (geolocation / ASN)

info = ch.info("check-host.cc")

WHOIS / RDAP lookup

record = ch.whois("check-host.cc")
# Returns the raw RDAP record (shape varies by registry).

Active Monitoring (POST tasks)

Each monitoring call returns a CheckCreated object with a uuid. Use report(uuid) (single fetch) or wait_for_report(uuid) (polling helper) to retrieve results.

Ping

# Minimal
task = ch.ping("8.8.8.8")

# With options
task = ch.ping(
    "8.8.8.8",
    region=["DE", "NL"],
    repeat_checks=5,           # >=10 enables Live Mode
    timeout=5,
)

DNS

from checkhost.regions import DNSType

# Minimal — defaults to A record
task = ch.dns("check-host.cc")

# Specific record type
task = ch.dns(
    "check-host.cc",
    query_method=DNSType.MX,    # A / AAAA / MX / TXT / NS / CAA / ...
    region=["US", "DE"],
)

TCP

# Minimal — host + port
task = ch.tcp("1.1.1.1", 443)

# With options
task = ch.tcp(
    "1.1.1.1",
    80,
    region=["DE", "NL"],
    repeat_checks=3,
    timeout=10,
)

UDP

The Check-Host backend knows sensible default payloads for well-known ports (DNS, NTP, SNMP, RIP, WireGuard, OpenVPN, Quake, Minecraft, …). Pass a custom hex (or printable) payload only when probing unusual services.

# Minimal — DNS query (default payload)
task = ch.udp("1.1.1.1", 53)

# Custom NTP payload to UDP/123
task = ch.udp(
    "pool.ntp.org",
    123,
    payload="0b",
    region=["EU"],
    repeat_checks=2,
)

HTTP

# Minimal — full URL
task = ch.http("https://check-host.cc")

# With options
task = ch.http(
    "https://check-host.cc/status",
    region=["EU"],
    repeat_checks=10,           # Live Mode: 11 probes over ~10s
)

MTR (My Traceroute)

from checkhost.regions import MTRProtocol, IPVersion

# Minimal
task = ch.mtr("1.1.1.1")

# Force TCP for ICMP-blocked paths
task = ch.mtr(
    "1.1.1.1",
    region=["EU"],
    repeat_checks=10,
    force_ip_version=IPVersion.V4,
    force_protocol=MTRProtocol.TCP,  # "udp" or "tcp"; default is ICMP
)

Results

Single fetch

report = ch.report(task.uuid)
print(report.is_complete, len(report.completed_nodes), report.pending_nodes)

Poll until complete

report = ch.wait_for_report(
    task.uuid,
    interval=1.5,            # clamped to >=1.0 (API limit)
    max_wait=30.0,
    require_complete=True,   # raise CheckHostTimeoutError on timeout
)

OG-Image (1200×630 PNG status map)

png_bytes = ch.og_image(task.uuid)

# Or write straight to disk
ch.save_og_image(task.uuid, "./status.png")

Country world map (SVG or PNG)

svg = ch.country_map(task.uuid)                                # default SVG
png_low = ch.country_map(task.uuid, format="png", resolution="low")    # 800px
png_high = ch.country_map(task.uuid, format="png", resolution="high")  # 2000px

# Convenience save
ch.save_country_map(task.uuid, "./status.svg")

API surface (reference table)

Method Endpoint Returns
ch.myip() GET /myip str
ch.myinfo() GET /myinfo MinResponseINFO
ch.locations() GET /locations dict[str, Any]
ch.info(target) POST /info MinResponseINFO
ch.whois(target) POST /whois dict[str, Any]
ch.ping(target, *, region=None, repeat_checks=0, timeout=None) POST /ping CheckCreated
ch.dns(target, *, query_method="A", region=None) POST /dns CheckCreated
ch.tcp(target, port, *, region=None, repeat_checks=0, timeout=None) POST /tcp CheckCreated
ch.udp(target, port, *, payload=None, region=None, repeat_checks=0, timeout=None) POST /udp CheckCreated
ch.http(target, *, region=None, repeat_checks=0, timeout=None) POST /http CheckCreated
ch.mtr(target, *, region=None, repeat_checks=10, force_ip_version=None, force_protocol=None) POST /mtr CheckCreated
ch.report(uuid) GET /report/{uuid} Report
ch.wait_for_report(uuid, *, interval=1.5, max_wait=30.0, require_complete=True) polls GET /report/{uuid} Report
ch.og_image(uuid) GET /report/{uuid}/og-image bytes (PNG)
ch.save_og_image(uuid, path) same Path
ch.country_map(uuid, *, format="svg", resolution="med") GET /report/{uuid}/country-map bytes
ch.save_country_map(uuid, path, *, format="svg", resolution="med") same Path

Client-side validation

The SDK rejects obviously bad input before issuing an HTTP call:

  • port: 1-65535
  • repeat_checks (non-MTR): 0-120
  • repeat_checks (MTR): 3-30
  • query_method: one of A, AAAA, MX, TXT, CAA, A/AAAA, … (full list in checkhost.regions.DNSType.ALL)
  • force_ip_version: 4 or 6
  • force_protocol: "icmp" | "udp" | "tcp"
  • country_map.format: "svg" | "png"
  • country_map.resolution: "low" | "med" | "high"

Use report.completed_nodes, report.pending_nodes and report.is_complete to inspect progress; report.raw always preserves the raw API payload, including any future fields the SDK doesn't yet surface explicitly.

Constants

from checkhost.regions import Continent, DNSType, IPVersion, MTRProtocol

Continent.EUROPE         # "EU"
Continent.ALL            # ("EU", "NA", "SA", "AS", "AF", "OC")

DNSType.MX               # "MX"
DNSType.A_AAAA           # "A/AAAA" - Swagger 2.0 compound default
DNSType.ALL              # ("A/AAAA", "A", "AAAA", "NS", ..., "DNSKEY")

IPVersion.V4             # 4
MTRProtocol.TCP          # "tcp"

Error handling

from checkhost import (
    CheckHost,
    CheckHostBadRequestError,
    CheckHostError,
    CheckHostNetworkError,
    CheckHostRateLimitError,
    CheckHostTimeoutError,
    CheckHostValidationError,
)

with CheckHost() as ch:
    try:
        task = ch.ping("1.1.1.1")
        report = ch.wait_for_report(task.uuid, max_wait=15.0)
    except CheckHostValidationError as exc:
        # Invalid input - fix the call.
        ...
    except CheckHostRateLimitError as exc:
        # 429: provide an API key or back off.
        ...
    except CheckHostBadRequestError as exc:
        # 400: bad payload.
        print(exc.status, exc.response)
    except CheckHostTimeoutError:
        # Polling deadline expired.
        ...
    except CheckHostNetworkError:
        # Connectivity / DNS / TLS issue.
        ...
    except CheckHostError:
        # Catch-all for the SDK.
        ...

Hierarchy at a glance:

CheckHostError
+-- CheckHostNetworkError
+-- CheckHostTimeoutError
+-- CheckHostValidationError       (also ValueError)
+-- CheckHostAPIError
    +-- CheckHostBadRequestError   (400)
    +-- CheckHostNotFoundError     (404)
    +-- CheckHostRateLimitError    (429)
    +-- CheckHostServerError       (5xx)

Logging

The SDK uses the standard logging module under the logger name "checkhost". Enable debug logs to inspect every outgoing HTTP request:

import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("checkhost").setLevel(logging.DEBUG)

Proxies and TLS

urllib.request from the standard library is used, which means HTTP_PROXY / HTTPS_PROXY / NO_PROXY environment variables are honoured automatically and TLS verification follows the system trust store.

Development

git clone https://git.check-host.eu/Check-Host/python-lib
cd python-lib
pip install -e ".[dev]"
pytest                      # 155 unit tests, ~0.2s
ruff check . && mypy checkhost

To run the integration tests against the live API (consumes real rate-limit budget — set CHECK_HOST_API_KEY for higher quotas):

pytest -m live              # 8 live tests, ~6s with an API key

License

Apache-2.0

Related libraries

Full API reference: https://check-host.cc/docs.

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

check_host_api-1.0.1.tar.gz (57.0 kB view details)

Uploaded Source

Built Distribution

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

check_host_api-1.0.1-py3-none-any.whl (36.0 kB view details)

Uploaded Python 3

File details

Details for the file check_host_api-1.0.1.tar.gz.

File metadata

  • Download URL: check_host_api-1.0.1.tar.gz
  • Upload date:
  • Size: 57.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for check_host_api-1.0.1.tar.gz
Algorithm Hash digest
SHA256 30dd01890f31565cfe41d1d64326f46d9fef697aadee5a7af91fca27089b0b1a
MD5 58f6765cde85c64eab50e7eab10e8bcf
BLAKE2b-256 b12fc84892777f7bc8bb8fd0348fb8f9a1cdb5e8402a6d3831abd91e77384684

See more details on using hashes here.

File details

Details for the file check_host_api-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: check_host_api-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 36.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for check_host_api-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b62d059ed4a7e5e88855044b8e01aaf2fae9e17b9e1c966d8bb53bb4a01949c7
MD5 463cadec6a1566c9965ceab46ca30135
BLAKE2b-256 5d6eca041864dfe8ebc3462703f7ccdceb05aad6d68c371bbf37f87bb79d3971

See more details on using hashes here.

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