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.1.tar.gz (19.0 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.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: taxql-0.2.1.tar.gz
  • Upload date:
  • Size: 19.0 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.1.tar.gz
Algorithm Hash digest
SHA256 cb8fa41d29ec4d4a73c5c31020f772b355c042c01740dd0de6d3fec4f050e299
MD5 17106deb19ce1b2f8135997820c4d23b
BLAKE2b-256 b44a5c14a2669df22c9eedde8181acaa361853774d0c139379aa3d1175d5550c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: taxql-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 15.9 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 000547fe501f66945b836b9b33c19c69e6cf6aa0b4ef704879d596a282d8c1d9
MD5 15ff554f72b0b6c56ce7713abd8ace34
BLAKE2b-256 0a6afcd5b5749861d57eb25573bd33743082b7374ee934cc1d73ca523456fb25

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 files

0.2.0

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