Skip to main content

DNScale Python SDK

The official Python client for the DNScale API. It supports Python 3.10 and newer, provides synchronous and asynchronous calls, and is generated from the public OpenAPI contract bundled as openapi.yaml.

Installation

Install a published release from PyPI:

python -m pip install dnscale

The distribution and import name are both dnscale; the source repository is dnscale-python. Before the first PyPI release, or to work from source, clone this repository and install from its root:

python -m pip install .

Quick start

Create an API key in the DNScale dashboard and pass it directly or export it as DNSCALE_API_KEY.

from dnscale import DNScale

with DNScale() as dns:
    zones = dns.zones.list(limit=25)
    for zone in zones.zones:
        print(zone.id, zone.name)

    created = dns.records.create(
        zones.zones[0].id,
        name="www",
        type_="A",
        content="192.0.2.10",
        ttl=300,
    )
    print(created.id)

The same resources provide async methods prefixed with a:

from dnscale import DNScale


async def list_zone_names() -> list[str]:
    async with DNScale() as dns:
        result = await dns.zones.alist(limit=100)
        return [zone.name for zone in result.zones]

DNScale retries transient failures for GET, HEAD, and OPTIONS requests. It never automatically retries mutations such as record or zone creation. Set max_retries=0 to disable retries. If Retry-After exceeds the 30-second retry waiting budget, the response is surfaced immediately instead of retrying before the server permits it. HTTP-date and numeric delay values are supported. Network errors remain httpx errors.

Pagination and record identity

list() returns one page. Use lazy iterators to traverse all pages:

with DNScale() as dns:
    for zone in dns.zones.iter():
        for record in dns.records.iter(zone.id):
            print(zone.name, record.name, record.content)

Async equivalents are zones.aiter() and records.aiter(zone_id). Iterators honour the returned page size and reject inconsistent pagination. Offset-based listing is not an atomic snapshot if another client changes the zone concurrently.

Record IDs are opaque and content-derived: use the returned ID after an update. By-name helpers can avoid retaining an ID:

from dnscale_api.models import UpdateRecordByNameRequest

with DNScale() as dns:
    updated = dns.records.update_by_name(
        zone_id, "_acme-challenge.example.com.", "TXT",
        content="old-value",  # select this value in a multi-value RRset
        body=UpdateRecordByNameRequest(content="new-value", ttl=300),
    )
    dns.records.delete_by_name(zone_id, updated.name, "TXT", content="new-value")

Omitting content from delete_by_name() deletes the entire RRset. Empty content is rejected by the helper to prevent accidental whole-RRset deletion. Async variants are aupdate_by_name() and adelete_by_name().

Errors

The convenience resources convert the API's error envelope into exceptions:

from dnscale import APIError, DNScale, RateLimitError

try:
    with DNScale() as dns:
        dns.zones.get("00000000-0000-0000-0000-000000000000")
except RateLimitError as error:
    print(error.retry_after)
except APIError as error:
    print(error.status_code, error.code, error.message, error.request_id)

Network and timeout failures remain standard httpx exceptions.

Complete generated API

The dnscale layer offers concise zone and record CRUD. Every public endpoint is also available through the generated dnscale_api package, including alerts, DNSSEC, usage, billing, users, invitations, API keys, activity, and DNS Control.

from dnscale import DNScale
from dnscale_api.api.usage import get_current_usage

with DNScale(api_key="your-api-key") as dns:
    response = get_current_usage.sync(client=dns.client)
    print(response)

Each generated operation has sync, sync_detailed, asyncio, and asyncio_detailed variants. Request and response models live in dnscale_api.models.

Development

From this repository's root, install development dependencies and regenerate the client. Python 3.10+ and uv are required. Do not edit dnscale_api by hand.

python -m pip install -e '.[dev]'
bash scripts/generate.sh

The generator version is pinned in the script. To verify the package:

python -m pytest
ruff check dnscale tests
ruff format --check dnscale tests
uv build

The generator is pinned; see GENERATION.md for the contract update policy. Commit the reviewed generated changes with their input changes.

Live verification is explicitly opt-in and creates/deletes a unique test zone:

export DNSCALE_TEST_BASE_URL=https://your-sandbox.example/v1
export DNSCALE_TEST_API_KEY=your-disposable-account-key
DNSCALE_LIVE_TEST=1 python -m pytest tests/test_live.py

The test uses separate credentials from DNSCALE_API_KEY. Use a disposable account with zone and record read/write scopes. No real domain delegation is needed. Tests are skipped when DNSCALE_LIVE_TEST is not 1.

Report bugs and feature requests in the issue tracker.

Metadata

Release files for dnscale 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dnscale 1.0.0
File Size Uploaded
dnscale-1.0.0.tar.gz 94.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dnscale 1.0.0
File Interpreter ABI Platform
dnscale-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 311.0 kB

Release files / dnscale-1.0.0.tar.gz

Download URL dnscale-1.0.0.tar.gz
Size 94.5 kB
Tags Source
SHA-256 checksum
How to use checksums
9ae6cdd5cc290233ab7ffb2d3020293e5033a0db90f168f4f57299d10c750233
BLAKE2b-256 checksum
How to use checksums
f1fe34626115aa0fdde230160b89182be20a7c091870b4d0d7aab5267ceddbbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14

Release files / dnscale-1.0.0-py3-none-any.whl

Download URL dnscale-1.0.0-py3-none-any.whl
Size 216.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
caf5e3ddb3d94f96e869de225653e459909d99a02ac1b079b6690b862efe4a2b
BLAKE2b-256 checksum
How to use checksums
6a63c71d054a9e3488feb6d07540c3b22eec3c3bfbac498bd4e170996119948f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.14

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page