EU VAT Number (Generic) Regex for Python
/^(?!US)(?![0-9]+$)(?:(?:AT)?U[0-9]{8}|(?:BE)?0[0-9]{9}|(?:BG)?[0-9]{9,10}|(?:CY)?[0-9]{8}[A-Z]|(?:CZ)?[0-9]{8,10}|(?:DE)?[0-9]{9}|(?:DK)?[0-9]{8}|(?:EE)?[0-9]{9}|(?:EL|GR)?[0-9]{9}|(?:ES)?[A-Z][0-9]{7}[A-Z]|(?:FI)?[0-9]{8}|(?:FR)?[A-Z0-9]{2}[0-9]{9}|(?:HR)?[0-9]{11}|(?:HU)?[0-9]{8}|(?:IE)?[0-9][A-Z0-9+*][0-9]{5}[A-Z]{1,2}|(?:IT)?[0-9]{11}|(?:LT)?(?:[0-9]{9}|[0-9]{12})|(?:LU)?[0-9]{8}|(?:LV)?[0-9]{11}|(?:MT)?[0-9]{8}|(?:NL)?[0-9]{9}B[0-9]{2}|(?:PL)?[0-9]{10}|(?:PT)?[0-9]{9}|(?:RO)?[0-9]{2,10}|(?:SE)?[0-9]{12}|(?:SI)?[0-9]{8}|(?:SK)?[0-9]{10})$/What this pattern does
This page provides a comprehensive, battle-tested regular expression for matching eu vat number (generic), ported and verified for Python. Financial data validation has zero tolerance for false negatives — a missed invalid entry can corrupt downstream calculations. The snippet below is ready to drop into your Python project — whether you're validating in a Django view, a FastAPI endpoint, or a standalone data processing script.
Python Implementation
# EU VAT Number (Generic)
# ReDoS-safe | RegexVault — Finance > Tax & Registration
import re
eu_vat_number_generic_pattern = re.compile(r'^(?!US)(?![0-9]+$)(?:(?:AT)?U[0-9]{8}|(?:BE)?0[0-9]{9}|(?:BG)?[0-9]{9,10}|(?:CY)?[0-9]{8}[A-Z]|(?:CZ)?[0-9]{8,10}|(?:DE)?[0-9]{9}|(?:DK)?[0-9]{8}|(?:EE)?[0-9]{9}|(?:EL|GR)?[0-9]{9}|(?:ES)?[A-Z][0-9]{7}[A-Z]|(?:FI)?[0-9]{8}|(?:FR)?[A-Z0-9]{2}[0-9]{9}|(?:HR)?[0-9]{11}|(?:HU)?[0-9]{8}|(?:IE)?[0-9][A-Z0-9+*][0-9]{5}[A-Z]{1,2}|(?:IT)?[0-9]{11}|(?:LT)?(?:[0-9]{9}|[0-9]{12})|(?:LU)?[0-9]{8}|(?:LV)?[0-9]{11}|(?:MT)?[0-9]{8}|(?:NL)?[0-9]{9}B[0-9]{2}|(?:PL)?[0-9]{10}|(?:PT)?[0-9]{9}|(?:RO)?[0-9]{2,10}|(?:SE)?[0-9]{12}|(?:SI)?[0-9]{8}|(?:SK)?[0-9]{10})$')
def validate_eu_vat_number_generic(value: str) -> bool:
return bool(eu_vat_number_generic_pattern.fullmatch(value))
# Example
print(validate_eu_vat_number_generic("DE123456789")) # TrueTest Cases
Matches (Valid) | Rejects (Invalid) |
|---|---|
DE123456789 | US123456789 |
FR12345678901 | 123456789 |
GB123456789 | DE12345678 |
IT12345678901 | FR1234567890A |
NL123456789B01 | — |
When to use this pattern
This pattern is drawn from the Finance > Tax & Registration category and carries a ReDoS-safe certification. That matters for Python developers because particularly important in Python web servers where CPU-bound regex operations can stall concurrent request handling. RegexVault audits patterns against known backtracking attack vectors, ensuring you have the necessary context before using this regex in a high-stakes production environment.
Common Pitfalls
Format validation alone does not confirm a VAT number is registered and active. Use the EU VIES (VAT Information Exchange System) web service for real-time validation.
Technical Notes
Each EU member state has a distinct VAT number format. This pattern covers all 27 EU member states. The country prefix is optional in this pattern — some systems present numbers without it. UK (GB) left SEPA in 2021 but the pattern is included for legacy data.
Have a pattern that belongs in the vault?
Submit it for review — community-verified patterns get credited to your GitHub handle. Free submissions join the queue. Priority review available for $15.
Submit a Pattern