Skip to main content

Demografix Python SDK

Predict gender, age, and nationality from names. The Python SDK covers all three Demografix APIs — genderize.io (gender), agify.io (age), and nationalize.io (nationality) — with single-name lookups and batches of up to 100 names per request. Synchronous and asynchronous clients share the same methods and models.

PyPI CI License: MIT

Install

pip install demografix

The SDK requires Python 3.10 or newer. The asynchronous client uses httpx.

Quickstart

Construct a client, run a list of names through a batch call, read the predictions, and read the quota.

from collections import Counter
from demografix import Demografix

client = Demografix(api_key="YOUR_API_KEY")

names = ["michael", "matthew", "jane", "sofia", "lars"]

batch = client.genderize_batch(names)

split = Counter(r.gender or "unknown" for r in batch.results)
print(split)                      # Counter({'male': 3, 'female': 2})
print(batch.quota.remaining)      # 24987

Async client

AsyncDemografix mirrors the synchronous API with native async HTTP. Use one client across requests so its connection pool can be reused, and close it with async with or aclose().

import asyncio
from collections import Counter
from demografix import AsyncDemografix

async def main():
    names = ["michael", "matthew", "jane", "sofia", "lars"]

    async with AsyncDemografix(api_key="YOUR_API_KEY") as client:
        genders, ages, nationalities = await asyncio.gather(
            client.genderize_batch(names),
            client.agify_batch(names),
            client.nationalize_batch(names),
        )

    split = Counter(r.gender or "unknown" for r in genders.results)
    print(split)
    print(nationalities.quota.remaining)

asyncio.run(main())

Task cancellation propagates normally. Network failures and timeouts raise TransportError, matching the synchronous client.

genderize

Predict gender from names. A single call returns the prediction fields plus a quota.

result = client.genderize("peter")
result.gender          # "male", "female", or None
result.probability     # 1.0
result.count           # 1352696
result.quota.remaining # 24987

The batch form reduces a list to a gender split.

batch = client.genderize_batch(["michael", "matthew", "jane"])
gender_mix = Counter(r.gender or "unknown" for r in batch.results)

gender is None when no match is found, with probability 0.0 and count 0. That is a successful response, not an error.

agify

Predict age from names. Aggregate a batch into an age distribution.

result = client.agify("michael")
result.age             # 57 or None
result.count           # 311558

batch = client.agify_batch(["michael", "matthew", "jane"])
ages = [r.age for r in batch.results if r.age is not None]
average_age = sum(ages) / len(ages)

age is an integer or None.

nationalize

Predict nationality from names. Each prediction carries up to five candidate countries in descending probability.

result = client.nationalize("nguyen")
result.country[0].country_id      # "VN"
result.country[0].probability     # 0.891132

batch = client.nationalize_batch(["nguyen", "schmidt", "rossi"])
top_countries = Counter(
    r.country[0].country_id for r in batch.results if r.country
)

country is an empty list when no match is found.

Batch limit

Each batch accepts at most 100 names. A batch of more than 100 raises ValidationError before any request goes out. Chunk a longer list and aggregate across the chunks.

def chunked(items, size=100):
    for i in range(0, len(items), size):
        yield items[i : i + size]

split = Counter()
for chunk in chunked(roster):
    batch = client.genderize_batch(chunk)
    split.update(r.gender or "unknown" for r in batch.results)

country_id

genderize and agify accept an optional country_id (ISO 3166-1 alpha-2) to scope the prediction to one country. Input is case-insensitive; the response echoes it uppercase on every prediction. nationalize has no such parameter.

result = client.genderize("kim", country_id="us")
result.country_id      # "US"

# Scope a whole list, then aggregate.
batch = client.agify_batch(["kim", "andrea", "jan"], country_id="us")
ages = [r.age for r in batch.results if r.age is not None]
batch.results[0].country_id   # "US", echoed uppercase on each prediction

Scoping changes the prediction: andrea reads mostly female in the United States and mostly male in Italy. When the request sends no country_id, the field is None.

Quota

Every result and every raised error carries a quota read from the response headers. Quota is never cached on the client; read it from the returned value.

Field Meaning
limit names allowed in the current window
remaining names left in the current window
reset seconds until the window resets
batch = client.genderize_batch(["michael", "matthew"])
batch.quota.remaining

Errors

Non-2xx responses raise a typed exception. Transport failures raise TransportError. Every exception subclasses DemografixError and carries status, message, and quota (when the response included headers).

Exception Status Cause
AuthError 401 invalid or missing API key
SubscriptionError 402 expired freebie or inactive subscription
ValidationError 422 bad parameter, or a batch over 100 names (raised client-side)
RateLimitError 429 window exhausted; quota is always populated
DemografixError other non-2xx base class for the hierarchy
TransportError none network error, timeout, or non-JSON body

A RateLimitError carries quota, so reset tells you how long to wait before retrying.

import time
from demografix import Demografix, RateLimitError

client = Demografix(api_key="YOUR_API_KEY")
names = ["michael", "matthew", "jane"]

while True:
    try:
        batch = client.genderize_batch(names)
        break
    except RateLimitError as exc:
        time.sleep(exc.quota.reset)

Methods

Method Returns country_id
genderize(name, country_id=None) GenderizeResult yes
genderize_batch(names, country_id=None) Batch of GenderizePrediction yes
agify(name, country_id=None) AgifyResult yes
agify_batch(names, country_id=None) Batch of AgifyPrediction yes
nationalize(name) NationalizeResult no
nationalize_batch(names) Batch of NationalizePrediction no

A *Result exposes the prediction fields directly plus a quota. A Batch exposes results plus one quota for the whole response. Both Demografix and AsyncDemografix expose the methods above; await methods on AsyncDemografix. Each constructor takes api_key and an optional timeout=10.0. The host URLs and the User-Agent are fixed constants, not options.

AsyncDemografix supports async with and aclose() to close its connection pool. The synchronous client retains its existing lifecycle and requires no explicit cleanup.

API keys

An API key is required. Creating one is free and includes 1,000 names per month.

Quota counts names, not requests. A single-name call costs 1. A batch of 100 names costs 100. The free tier therefore covers 1,000 names in a month however they are split across calls.

Generate a key in your dashboard at genderize.io, agify.io, or nationalize.io. One key works across all three services. Full reference: genderize.io/documentation/api.

License

MIT. See LICENSE.

Metadata

Release files for demografix 0.3.1

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

Source distribution (sdist)

Source distribution for demografix 0.3.1
File Size Uploaded Provenance Actions
demografix-0.3.1.tar.gz 27.0 kB With provenance Details for demografix-0.3.1.tar.gz

Built distribution (wheel)

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

Total release size: 39.5 kB

Release files / demografix-0.3.1.tar.gz

Download URL demografix-0.3.1.tar.gz
Size 27.0 kB
Tags Source
SHA-256 checksum
How to use checksums
59580655391759e1ea7782bd1a8a91d88ca1e5c28e1eb4d31ddb769109bf9810
BLAKE2b-256 checksum
How to use checksums
8ac9b8307190e5c4100b2796858fbad15ec9148c6cfb9a3bc5d3996804a95f97
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / demografix-0.3.1-py3-none-any.whl

Download URL demografix-0.3.1-py3-none-any.whl
Size 12.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4405c945a0f1e9e90f8c688c3e191c5e010315cee9438b8e9b9828e0de2c54b8
BLAKE2b-256 checksum
How to use checksums
c6b84912b986278d8c71d8e5f651c415fb0723816e6bff7d21f86c945e1e1138
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Security for demografix 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for demografix-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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