How to Validate Australian Business Numbers (ABN) in Python
ABN validation goes beyond a simple format check. Here's how the checksum works, why you need an ABR lookup, and how to get it right with a single API call.
In this guide
1. What is an ABN?
An Australian Business Number (ABN) is a unique 11-digit identifier assigned to all business entities operating in Australia. It is issued by the Australian Business Register (ABR) and is used for tax reporting, invoicing, GST registration, and government interactions.
Every company, sole trader, partnership, trust, and government body in Australia has an ABN. If your application processes Australian business data — whether for invoicing, onboarding suppliers, or compliance checks — you need to validate ABNs correctly.
2. The structure of an ABN
An ABN consists of 11 digits, typically displayed in the format XX XXX XXX XXX:
| Digits | Purpose |
|---|---|
| 1–2 | Check digits (derived from the remaining 9 digits) |
| 3–11 | Unique identifier for the entity (based on the previous tax file number for companies) |
For example, the ABN 51 824 753 556 has check digits 51 and entity identifier 824753556.
3. The ABN checksum algorithm
The ABN uses a weighted modulus-89 check digit algorithm. Here's how it works:
- Subtract 1 from the first (leftmost) digit of the ABN.
- Multiply each of the 11 digits by its corresponding weight:
10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19. - Sum all 11 weighted products.
- Divide the sum by 89. If the remainder is zero, the ABN is valid.
# ABN checksum verification (for illustration only) WEIGHTS = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] def is_valid_abn(abn: str) -> bool: digits = [int(c) for c in abn.replace(" ", "") if c.isdigit()] if len(digits) != 11: return False # Step 1: subtract 1 from the first digit digits[0] -= 1 # Step 2–3: weighted sum total = sum(d * w for d, w in zip(digits, WEIGHTS)) # Step 4: check divisibility by 89 return total % 89 == 0 is_valid_abn("51 824 753 556") # True is_valid_abn("51 824 753 557") # False — checksum fails
4. Basic validation vs business lookup
There are two levels of ABN verification, and the right choice depends on your use case:
Format + checksum validation
Checks that the ABN is exactly 11 digits and passes the modulus-89 checksum. This is instant and does not require any external lookup. Use this for form validation where you just need to catch typos.
ABR registry lookup
Queries the Australian Business Register to confirm the ABN is active and retrieves entity details — business name, entity type, GST registration status, state, postcode, and trading names. Use this for supplier onboarding, invoice verification, or compliance workflows where you need to confirm the business actually exists.
lookup parameter for a fast format check, or set it to True to query the ABR and get full entity details.5. The right solution: one API call
Instead of implementing the checksum yourself and integrating with the ABR separately, use the IsValid ABN API. A single GET request handles format validation, checksum verification, and optional ABR lookup — returning entity name, type, GST status, and more.
Get your free API key at isvalid.dev. The free tier includes 100 calls per day — enough for most development and low-volume production use.
Full parameter reference and response schema: ABN Validation API docs →
6. Python code example
Using the isvalid-sdk Python SDK or the requests library. Install with pip install isvalid-sdk or pip install requests.
# abn_validator.py import os from isvalid_sdk import IsValidConfig, create_client iv = create_client(IsValidConfig(api_key=os.environ["ISVALID_API_KEY"])) # ── Basic validation ──────────────────────────────────────────────────────── result = iv.au.abn("51824753556") print(result["valid"]) # True print(result["abn"]) # '51824753556' print(result["formatted"]) # '51 824 753 556' # ── With business lookup ──────────────────────────────────────────────────── lookup = iv.au.abn("51824753556", lookup=True) print(lookup["entityName"]) # 'GOOGLE AUSTRALIA PTY LTD' print(lookup["entityType"]) # 'Australian Private Company' print(lookup["gstRegistered"]) # True print(lookup["state"]) # 'NSW'
result["valid"]) from the ABR lookup results. A valid checksum does not guarantee the business is active — always use lookup=True when you need to confirm entity details.7. cURL example
Basic format + checksum validation (fast, no ABR call):
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/au/abn?value=51824753556"
With ABR business lookup (retrieves entity details):
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/au/abn?value=51824753556&lookup=true"
8. Understanding the response
Basic validation response (no lookup):
{ "valid": true, "abn": "51824753556", "formatted": "51 824 753 556" }
Response with lookup=true:
{ "valid": true, "abn": "51824753556", "formatted": "51 824 753 556", "found": true, "entityName": "GOOGLE AUSTRALIA PTY LTD", "entityType": "Australian Private Company", "abnStatus": "Active", "abnStatusFrom": "2000-07-01", "acn": "824753556", "state": "NSW", "postcode": "2060", "gstRegistered": true, "businessNames": [], "dataSource": "abr.business.gov.au" }
| Field | Type | Description |
|---|---|---|
| valid | boolean | Format and checksum are correct |
| abn | string | Normalized 11-digit ABN (spaces removed) |
| formatted | string | Display format: XX XXX XXX XXX |
| found | boolean | Whether the ABN was found in the ABR (lookup only) |
| entityName | string | null | Registered entity name from ABR |
| entityType | string | null | Entity type (e.g. Australian Private Company, Sole Trader) |
| abnStatus | string | null | Current status (Active, Cancelled) |
| abnStatusFrom | string | null | Date the current status took effect (YYYY-MM-DD) |
| acn | string | null | Australian Company Number (if applicable) |
| state | string | null | State or territory (e.g. NSW, VIC, QLD) |
| postcode | string | null | Registered postcode |
| gstRegistered | boolean | Whether the entity is registered for GST |
| businessNames | string[] | Registered trading / business names |
| dataSource | string | null | Data source used for the lookup |
When lookup is omitted or False, only valid, abn, and formatted are returned.
9. Edge cases to handle
Cancelled ABNs
An ABN can be cancelled when a business ceases operations. The number remains syntactically valid and passes the checksum, but the ABR returns abnStatus: "Cancelled". Always check the status field when using lookup mode — do not assume a found ABN is an active business.
# Handle cancelled ABNs result = iv.au.abn("51824753556", lookup=True) if result["valid"] and result.get("found") and result.get("abnStatus") != "Active": # ABN exists but is no longer active print(f"ABN cancelled since {result['abnStatusFrom']}") raise ValueError("ABN is not currently active")
GST registration status
Not every active ABN is registered for GST. Businesses with annual turnover below $75,000 (or $150,000 for non-profits) are not required to register. If your workflow depends on GST status — for example, determining whether to include GST on an invoice — always check the gstRegistered field.
if result["valid"] and result.get("found"): if result["gstRegistered"]: # Include GST on invoice apply_gst(invoice) else: # No GST — entity is not GST-registered print("Entity is not registered for GST")
Multiple business names
A single ABN can have multiple registered trading names (business names). The entityName field returns the legal entity name, while businessNames contains a list of registered trading names. When matching against user-provided company names, check both fields.
# Check both entity name and trading names all_names = [result["entityName"]] + result.get("businessNames", []) all_names = [n for n in all_names if n] user_input = "Google Australia" match = any( user_input.lower() in name.lower() for name in all_names )
Network failures
Always wrap the API call in a try/except. A network timeout should not cause your application to crash — decide upfront whether to fail open or closed on API unavailability.
def validate_abn_safe(abn: str, **kwargs) -> dict: try: return validate_abn(abn, **kwargs) except requests.RequestException as exc: # Log and decide: fail open (allow) or fail closed (reject) logger.error("ABN validation failed: %s", exc) return {"valid": None, "error": "validation_unavailable"}
Summary
See also
Try ABN validation instantly
Free tier includes 100 API calls per day. No credit card required. Format validation plus optional ABR business lookup.