How to Validate VAT Numbers in Python
Validate a VAT number in Python with the Avatcado SDK. The response includes its registration status and company details when the registry provides them. This guide covers a single lookup, errors, and an async request.
Install the Python package
Use Python 3.9 or later and an Avatcado account. Single-number validation is available on Free, with 500 live validations per month. These examples were checked with Python 3.14.3 and SDK 0.6.0.
python -m venv .venv
source .venv/bin/activate
python -m pip install avatcado==0.6.0
export AVATCADO_API_KEY="avat_test_replace_with_your_key"On Windows, activate the environment with .venv\Scripts\Activate.ps1 in PowerShell and set $env:AVATCADO_API_KEY="avat_test_replace_with_your_key". Use a test key from your dashboard. The sample number below returns a fixed test result.
Get your free API key to run this example.
Validate a VAT number
Save this as validate_vat.py and run python validate_vat.py.
import os
from avatcado import Avatcado, AvatcadoError
with Avatcado(os.environ["AVATCADO_API_KEY"], timeout=30.0) as client:
try:
result = client.vat.validate("DE111111111")
print(f"Valid: {result.data.valid}")
print(f"Number: {result.data.vat_number}")
company = result.data.company
print(f"Company: {company.name if company else 'Not provided'}")
print(f"Mode: {result.meta.mode}")
except AvatcadoError as error:
print(f"Request failed: {error.code}: {error.message}")
print(f"HTTP status: {error.status_code}")
print(f"Request ID: {error.request_id}")With a test key, DE111111111 returns Valid: True, company name Test GmbH, and Mode: test. Test calls do not query government registries or consume your monthly quota. Keep the key in the environment and out of source control.
Read the response
| Python field | Value |
|---|---|
result.data.valid | Registration status reported by the source. |
result.data.vat_number | The normalized VAT number. |
result.data.company | Company details, or None. The address may also be absent. |
result.data.requested_at | The request timestamp. |
result.meta.source | The registry or test source that supplied the result. |
result.meta.cached / result.meta.stale | Cache and freshness information when present. |
A successful request can return valid: false. Company details can be absent on a valid result. Check for None before reading the company object. Try DE222222222 with your test key to check that case.
Handle validation errors
SDK methods raise AvatcadoError subclasses for failed requests. The example prints the error code and request ID. In an application, retain those fields for troubleshooting and present the relevant error to the caller. An error leaves the registration status unresolved.
| Test input or condition | Result | Action |
|---|---|---|
DE000000000 | Successful lookup with valid: false. | Handle an invalid registration. |
DE123 | invalid_vat_format | Ask for a correctly formatted number. |
| Missing or incorrect key | unauthorized | Check the API-key configuration. |
DE777777777 | rate_limit_exceeded | Check the quota and any retry guidance. |
DE999999999 | upstream_unavailable | Record the failure and try again later. |
Handle unavailable registries
Live requests may use eligible cached data during an outage. Pro and Business also support national-register fallback for covered countries. Inspect the response metadata to see its source and freshness. If no eligible source can answer, the API returns a 503 error. The SDK does not retry requests automatically.
Keep the existing tax treatment and error policy in your application explicit. A failed lookup provides no new registration result. See the VIES downtime guide for the available response paths.
Use the async Python client
Use AsyncAvatcado in an asyncio application. This example awaits the single-validation endpoint. Avatcado also has separate background-validation endpoints with their own plan requirements.
import asyncio
import os
from avatcado import AsyncAvatcado, AvatcadoError
async def main():
async with AsyncAvatcado(os.environ["AVATCADO_API_KEY"], timeout=30.0) as client:
try:
result = await client.vat.validate("DE111111111")
print(result.data.valid)
except AvatcadoError as error:
print(f"Request failed: {error.code}: {error.message}")
asyncio.run(main())Switch to live validation
Set AVATCADO_API_KEY to your avat_live_ key and replace the sample number with the number you need to check. Keep the country prefix. Live requests use your plan quota.
For files containing multiple numbers, follow the Python CSV guide. For a JavaScript application, see the TypeScript guide. The API integration guide covers the supported registries. The test-mode reference lists the remaining fixtures.
Sources
- Avatcado Python SDK 0.6.0 Avatcado, accessed September 22, 2026
- Python asyncio documentation Python Software Foundation, accessed September 22, 2026
Related guides
How to Validate VAT Numbers in TypeScript
Validate EU, UK, Swiss, Norwegian, and Australian VAT/GST numbers in TypeScript with @avatcado/node. Covers error handling, batch validation, and test mode.
Validate EU VAT Numbers via API: Developer Guide
Learn how to validate EU VAT numbers, plus UK, Swiss, Norwegian, and Australian VAT/GST, via REST API. Covers VIES, HMRC, TypeScript, Python, and test mode.
Validate VAT Numbers from a CSV with Python
Validate a CSV of VAT numbers with Python. Process batches of 50, keep row order, record errors, and export results using the Avatcado SDK.