Guide · Python · SDK · REST API

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.

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:

DigitsPurpose
1–2Check digits (derived from the remaining 9 digits)
3–11Unique 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:

  1. Subtract 1 from the first (leftmost) digit of the ABN.
  2. Multiply each of the 11 digits by its corresponding weight: 10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19.
  3. Sum all 11 weighted products.
  4. 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
⚠️Implementing this yourself handles only format validation. A checksum-valid ABN might still be cancelled, not yet active, or belong to a deregistered entity. You need an ABR lookup to confirm the business is real and current.

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.

ℹ️The IsValid API supports both modes. Omit the 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.

Instant
Validation
format + checksum
Optional
ABR lookup
entity details
100/day
Free tier
no credit card

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'
Always separate format/checksum validation (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"
}
FieldTypeDescription
validbooleanFormat and checksum are correct
abnstringNormalized 11-digit ABN (spaces removed)
formattedstringDisplay format: XX XXX XXX XXX
foundbooleanWhether the ABN was found in the ABR (lookup only)
entityNamestring | nullRegistered entity name from ABR
entityTypestring | nullEntity type (e.g. Australian Private Company, Sole Trader)
abnStatusstring | nullCurrent status (Active, Cancelled)
abnStatusFromstring | nullDate the current status took effect (YYYY-MM-DD)
acnstring | nullAustralian Company Number (if applicable)
statestring | nullState or territory (e.g. NSW, VIC, QLD)
postcodestring | nullRegistered postcode
gstRegisteredbooleanWhether the entity is registered for GST
businessNamesstring[]Registered trading / business names
dataSourcestring | nullData 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

Do not rely on a simple length check — use the modulus-89 checksum
Do not treat checksum-valid as actively registered
Use checksum validation for fast form-level checks
Use ABR lookup to confirm entity status and GST registration
Check abnStatus — cancelled ABNs still pass checksum
Handle multiple business names when matching entity data

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.