Skip to main content

TaxQL Python SDK

Official Python client for the TaxQL API. Address-accurate U.S. sales tax lookups across all 50 states + DC, plus Canada (GST/HST/QST for all 13 provinces and territories, in beta).

pip install taxql

Quickstart

from taxql import TaxQL

client = TaxQL(api_key="your-key")

response = client.lookup(
    state="tx",
    address="6515 Cottonwood Creek Dr, Frisco, TX 75034",
)

print(f"Rate: {response.combined_rate * 100:.4f}%")
print(f"State: {response.rate.state}  County: {response.rate.county}")
print(f"Confidence: {response.confidence}")

Output:

Rate: 8.2500%
State: TX  County: COLLIN
Confidence: exact

Why TaxQL

  • Address-accurate, not ZIP-approximated. We resolve to the jurisdiction at the address (including SPDs / ESDs / MUDs), not the city in the address line.
  • Best rate by default. Each lookup returns a single applicable rate plus a confidence signal and any advisory warnings.
  • Historical queries. Pass as_of=date(2026, 6, 1) to retrieve the rate in effect on that date.
  • Half the price of incumbent providers.

Lookup modes

Provide exactly one input mode per call:

# Address (highest precision) — pass a full single-line address
client.lookup(state="tx", address="6515 Cottonwood Creek Dr, Frisco, TX 75034")

# ZIP only (single best rate; lower confidence on straddling ZIPs)
client.lookup(state="wa", zip="98039")

# Location name (DoR-published place name)
client.lookup(state="wa", location="Seattle")

# Lat/lng
client.lookup(state="ca", lat=34.05, lng=-118.25)

Response shape

lookup() returns a TaxResponse with a rate block and a meta block. Convenience properties cover the common path:

r = client.lookup(state="tx", address="...", city="...", zip="...")

r.combined_rate      # float accessor — total applicable rate, e.g. 0.0825
r.combined_rate_string  # "0.08250" — the lossless wire string
r.confidence         # "exact" | "high" | "medium" | "low" | "none"
r.warnings           # list of advisories (see below)

r.rate.state         # "TX"
r.rate.county        # "COLLIN"
r.rate.state_rate    # "0.06250" — wire STRING (since 0.2.0)
r.rate.state_rate_as_float()   # 0.0625 — explicit accessor
r.rate.combined_district_rate  # "0.02000" — sum of special-district rates

Since 0.2.0, rate fields are preserved as the API's fixed 5-decimal strings — never coerced to float, so binary floating point never touches tax arithmetic. Convert explicitly with rate_to_float(...), the Rate.*_as_float() accessors, or r.combined_rate (a float accessor); for exact money math read the string and use decimal.Decimal. Matches the PHP and Node SDKs. For the verbose per-jurisdiction body (every candidate row, component breakdown, resolved-place detail), request mode=full on the raw HTTP API.

Warnings

response.warnings is a list whose items are either plain strings or structured objects carrying a code:

for w in response.warnings:
    if isinstance(w, dict) and w.get("code") == "place_input_mismatch":
        print(f"input '{w['customer_input_place']}' resolved to "
              f"'{w['resolved_place_name']}'")
    elif isinstance(w, str):
        print(w)

Async client

import asyncio
from taxql import AsyncTaxQL

async def main():
    async with AsyncTaxQL(api_key="your-key") as client:
        # Three concurrent lookups
        responses = await asyncio.gather(
            client.lookup(state="tx", zip="75034"),
            client.lookup(state="wa", zip="98039"),
            client.lookup(state="ca", zip="94022"),
        )
        for r in responses:
            print(r.rate.state, f"{r.combined_rate * 100:.4f}%")

asyncio.run(main())

Historical queries

Pass as_of to retrieve the rate in effect on a specific date:

from datetime import date

# Q2 2026 (current as of 2026-06-01)
q2 = client.lookup(state="wa", zip="98039", as_of=date(2026, 6, 1))

# Q3 2026 (loaded ahead of effective date)
q3 = client.lookup(state="wa", zip="98039", as_of=date(2026, 7, 15))

Supported on states with effective-period history (TX, CA, FL, WA, NY, and all SST states). Single-snapshot states (NM, MO, IL, CO, LA, AL, AZ, AK) return the current rate regardless of as_of.

Error handling

from taxql import (
    TaxQL, AuthError, PaymentRequiredError, ForbiddenError,
    RateLimitError, NotFoundError, ValidationError, ServiceError, TaxQLError,
)

try:
    client.lookup(state="tx", zip="75034")
except AuthError:
    print("Invalid API key — sign up at https://taxql.com/signup")
except PaymentRequiredError:
    print("Billing/subscription issue — check the dashboard")   # 402
except ForbiddenError:
    print("Your plan doesn't include this")                     # 403
except RateLimitError as e:
    print(f"Rate limited; retry after {e.retry_after}s")
except NotFoundError:
    print("Address could not be resolved")
except ValidationError as e:
    print(f"Bad input: {e}")
except ServiceError:
    print("Upstream temporarily down")
except TaxQLError as e:
    print(f"Other API error [{e.error_code}] (ref {e.support_reference})")

The SDK automatically retries 429 (rate limit) and 5xx (service error) responses up to max_retries=3 times with exponential backoff (and honors the Retry-After header on 429). 4xx errors other than 429 raise immediately — no point retrying a malformed request. Every exception carries status_code and the parsed response_body (e.g. exc.response_body["error"]["code"]).

Configuration

TaxQL(
    api_key="your-key",
    base_url="https://api.taxql.com",   # default
    timeout=10.0,                        # seconds
    max_retries=3,                       # 429 + 5xx + timeout
    http_client=None,                    # inject your own httpx.Client
)

If you inject your own httpx.Client, the SDK won't close it on __exit__ — manage its lifecycle yourself. Useful for sharing a connection pool across multiple SDK instances or for custom transport (e.g., adding proxies or TLS cert pinning).

Forward compatibility

The response models use extra="allow" so newer API versions adding fields don't break older clients. You can always access the raw response dict via response.model_dump().

Examples

Runnable examples live in examples/:

  • examples/basic.py — sync address lookup, single state
  • examples/async_lookup.py — async, multiple states in parallel
  • examples/historical.pyas_of comparison across quarters

Documentation

Full API docs at https://docs.taxql.com. OpenAPI spec at https://api.taxql.com/openapi.json.

License

Commercial — see https://taxql.com/terms.

Support

support@taxql.com — or open an issue at https://github.com/taxql/taxql-python/issues.

Download files

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

Source Distribution

taxql-0.2.0.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

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

taxql-0.2.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file taxql-0.2.0.tar.gz.

File metadata

  • Download URL: taxql-0.2.0.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for taxql-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c3a689c1be64c9413c165e8bbbf3cca42806f3cd208a064d52fe616dbd15bfce
MD5 97062881d517153c9baa2bd23ab7b8b9
BLAKE2b-256 ab9feb4a970ff1687367934ca0595730b72eaafebccb8720ab482c05fec94284

See more details on using hashes here.

File details

Details for the file taxql-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: taxql-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for taxql-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 31d8001d29005a0dcca4896be19969f798406d472e4ae50154a40cf7fe6a0c15
MD5 ffba4c449b1bdb4b38682222aa417285
BLAKE2b-256 116f55f49996cf1ec4af970cf49c75c69f995e6b50c5676ad9b47640cf5597b0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

This release

0.2.0 This release

2 files

0.1.1

2 files

0.1.0

2 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