A customer in Berlin enters a French VAT number at checkout. Your tax engine recognizes a cross-border B2B transaction, switches to reverse charge, recalculates the invoice, and removes VAT from the line. The cart hasn't changed, but the tax treatment and invoice have.
That small field creates a surprisingly demanding backend problem. EU VAT numbers aren't validated by one universal pattern or one always-available API. In a production billing system, you need two layers: local syntax checks that reject obvious errors immediately, followed by an authoritative registry lookup through the European Commission's VIES service.
Table of Contents
- What EU VAT Numbers Actually Identify
- The Two-Letter Country Prefix and Why It Matters
- Regex and Syntax Rules You Can Validate Locally
- Quick Reference Table for EU Member State Formats
- How VIES Works as the Official Validation Layer
- What VIES Does Not Tell You
- Pre-Flight Validation Checklist Before Calling VIES
- Common Pitfalls Developers Hit in Production
- Direct VIES Versus a Managed Validation Layer
- Glossary of VAT and VIES Terms
- Frequently Asked Questions on EU VAT Numbers
What EU VAT Numbers Actually Identify
A VAT identification number is an identifier issued by a tax authority to a taxable person registered for value-added tax. In cross-border EU trade, it helps establish which member state assigned the registration and supports checks needed for certain intra-Community tax treatments. The European Commission describes VIES as the official mechanism for checking VAT numbers used in cross-border EU trade, and explicitly frames it as a search engine rather than a database. The Commission's VIES guidance explains that a check returns either valid or invalid, while a positive result may also include a registered name and address depending on the member state.
That definition is narrower than many applications assume. A VAT number isn't a company registration number, tax rate, legal entity identifier, or proof of every tax obligation held by a business. It confirms a VAT registration status within the scope of the relevant validation service and identifies the issuing jurisdiction.
Treat the identifier as a routing key
For engineers, the useful mental model is simple: a VAT number is a routing key, not an answer. Its country prefix tells your application which national format rules to apply and which member-state value to send to VIES. The remote response then tells you whether the number is recognized by the relevant national registry at the time of the check.
The identifier is country-specific in syntax but EU-wide in meaning. Austria, Germany, and France don't construct their numbers in the same way, yet each uses the number to identify a VAT registration for EU compliance workflows. That combination makes a two-layer design more reliable than sending every raw string directly to a remote service.
Start by normalizing the input, extracting the issuing code, and applying a country-specific pattern. Only after that should your system call VIES. This avoids wasting network requests on malformed values and gives users an immediate, actionable error when they mistype a prefix or add an unsupported character.
Practical rule: A syntactically valid number deserves a registry lookup. It doesn't deserve automatic tax treatment until the lookup succeeds.
The Two-Letter Country Prefix and Why It Matters
Most EU VAT identifiers begin with a two-letter country prefix, followed by a body defined by the issuing jurisdiction. The prefix usually corresponds to the country associated with the registration, but developers shouldn't treat the body as a shared EU format. The Commission's official VAT identification-number materials show that each member state maintains its own structure and validation rules while VIES provides a common access point.
Consider three ordinary-looking examples from the official format references:
- ATU12345678 begins with
AT, then includes a fixedUand a numeric body. - DE123456789 begins with
DEand continues with digits. - FR, followed by two alphanumeric characters and nine digits, uses a different structure again.
The prefix-body split matters because it drives both parsing and routing. Your formatter needs the prefix to choose the national rule. Your VIES payload needs the issuing member state separately from the identifier body. Treating the entire value as an opaque string makes it harder to validate, display, log, and troubleshoot.
Greece is the exception that catches weak implementations
Greece is the classic failure case. Its VAT identifier uses EL, not the ISO country code developers often expect, GR. The EU format reference includes Greece's EL convention, so a validator that accepts only GR will reject legitimate Greek registrations before they ever reach VIES. The EU VAT format reference shows the country-specific examples and reinforces why a generic ISO lookup isn't sufficient on its own.
This isn't merely a display issue. If your parser maps prefixes through a strict country table, GR may produce an unsupported-country error, while EL correctly selects Greece's syntax and VIES request data. Store the issuing code in its canonical VAT form, and preserve the user's original input separately for audit and support.
Northern Ireland introduces a related operational concern. VIES supports Northern Ireland for VAT validation purposes, so systems handling older invoices or cross-border records should avoid assuming that every historical or legacy-looking prefix belongs to a current EU member-state workflow. Keep the accepted prefix set explicit and versioned rather than hard-coding a casual two-letter allowlist.
Regex and Syntax Rules You Can Validate Locally
A coarse filter can remove obvious junk before you spend time on a registry request:
^[A-Z]{2}[A-Za-z0-9\-]{2,12}$
That pattern is useful as a first gate, but it isn't a country validator. It accepts combinations that no member state issues and may accept hyphens that belong only to a display representation. Use it to catch missing prefixes, implausible characters, and very short or long input. Then hand the normalized value to a rule selected by the prefix.
For a practical implementation, think in three stages:
- Normalize. Trim outer whitespace and uppercase the value.
- Route. Read the first two characters and select the member-state rule.
- Validate locally. Apply the exact structure for that jurisdiction before making a network call.
Digit-heavy formats aren't interchangeable
Germany's format is DE followed by nine digits, while Austria's is ATU followed by eight digits. The Austrian U isn't optional decoration. It's part of the format, so a rule that expects AT plus digits will reject valid Austrian values or incorrectly accept malformed ones.
France demonstrates why a digits-only assumption also fails. Its body includes two alphanumeric characters followed by nine digits, allowing letters in a defined position. A broad prefix pattern accepts this shape, but a French-specific rule should enforce the position and length rather than merely checking that the body contains allowed characters.
Greece adds another trap. Greek VAT values use EL and can include a trailing check character, so a validator that assumes every national body is digits only will create false negatives. The VAT number format glossary is a useful companion when documenting these distinctions for developers and support teams.
The regex is not the authority. It answers, “Could this string have the right shape?” VIES answers, “Does the issuing registry recognize it now?”
Some countries use hyphens in examples or printed documents, but your canonical internal value should have one deliberate representation. Decide whether your system strips permitted display separators or rejects them, then apply that decision consistently across checkout, CRM imports, invoices, and reconciliation jobs. Never let one integration compare a raw value with another integration's formatted value.
Quick Reference Table for EU Member State Formats
Use a format table as a working lookup, not as a substitute for the official registry. The useful contract has four parts: the member state, its country code, a pattern, and a structural note that tells the implementer what the regex does not express. The examples below are illustrative shapes based on the official EU reference material, not live registrations.
| Member State | Country Code | Pattern | Example | Structural Note |
|---|---|---|---|---|
| Austria | AT | ATU plus eight digits |
ATU12345678 |
The U is fixed in the VAT format. |
| Belgium | BE | BE plus digits |
BE0123456789 |
Numeric body, with formatting conventions handled separately. |
| Bulgaria | BG | BG plus digits |
BG123456789 |
Validate the official prefix representation, including Cyrillic-related display issues where applicable. |
| Croatia | HR | HR plus digits |
HR12345678901 |
Treat the body as numeric rather than broadly alphanumeric. |
| Cyprus | CY | CY plus digits |
CY12345678X |
The final character rule needs a country-specific check. |
| Czechia | CZ | CZ plus digits |
CZ12345678 |
Local rules can allow different numeric lengths. |
| Germany | DE | DE plus nine digits |
DE123456789 |
Digit-heavy format with a fixed body length. |
| Denmark | DK | DK plus eight digits |
DK12345678 |
Numeric body. |
| Estonia | EE | EE plus digits |
EE123456789 |
Numeric structure. |
| Greece | EL | EL plus digits and check character |
EL123456789 |
VAT prefix is EL, not GR. |
| France | FR | FR plus two alphanumeric characters and nine digits |
FRAB123456789 |
Letters are permitted in the defined prefix-body positions. |
| Hungary | HU | HU plus digits |
HU12345678 |
Numeric body. |
| Ireland | IE | IE plus digits and letters |
IE1234567X |
Country-specific suffix rules matter. |
| Italy | IT | IT plus eleven digits |
IT12345678901 |
Numeric body. |
| Luxembourg | LU | LU plus digits |
LU12345678 |
Numeric body. |
| Netherlands | NL | NL plus digits and B |
NL123456789B01 |
The B segment is structural, not arbitrary text. |
| Poland | PL | PL plus digits |
PL1234567890 |
Numeric body. |
| Portugal | PT | PT plus digits |
PT123456789 |
Numeric body. |
| Romania | RO | RO plus a variable numeric body |
RO123456789 |
Apply the national range rather than one universal length. |
| Spain | ES | ES plus letters and digits |
ESA1234567B |
Entity-type characters can be significant. |
| Sweden | SE | SE plus twelve digits |
SE123456789012 |
Numeric body. |
The table intentionally highlights divergence from a simple prefix-plus-digits model. Bulgarian representations can involve Cyrillic-prefixed forms, Croatia uses a pure-digits rule, Romania permits a variable digit range, and some jurisdictions retain optional business-unit suffix conventions. Confirm the current national rule before shipping a production parser.
The Greek anomaly belongs in your test fixtures: canonical VAT handling should round-trip Greek registrations as EL, even if a customer or legacy system supplies GR. Format validity only establishes shape. It doesn't establish registration, which is the job of VIES.
How VIES Works as the Official Validation Layer
VIES, the VAT Information Exchange System, is best understood as a federation layer. It doesn't operate as one central EU ledger containing every VAT record. Instead, the European Commission's service routes a request to the relevant national VAT database and returns the result through a common interface.
The Commission describes VIES as a search engine rather than a database. Its service exists so traders involved in intra-Community supplies can request confirmation of a specified VAT number, with the administrative cooperation basis formalized under Article 31 of Council Regulation (EC) No. 904/2010. The public VIES portal asks you to select the issuing member state and enter the number for verification.
The SOAP interface is the part developers inherit
The public integration is SOAP-based. Implementations commonly encounter the checkVat and checkVatApprox operations, along with an asynchronous batch equivalent and the published WSDL used to generate or configure a client. checkVat focuses on validity. checkVatApprox allows a trader name and address to be supplied for an approximate comparison, where the national service supports those fields.
A successful response is a point-in-time result. VIES queries national registries, so the answer reflects what those systems return during the request rather than a permanent guarantee about the business. National systems can also differ in the amount of name and address information they provide.
That architecture has two consequences. First, VIES is authoritative for the registry check but not necessarily fast or consistently available. Second, your application needs explicit handling for technical failures, timeouts, and incomplete enrichment fields instead of treating every non-success response as an invalid VAT number. A detailed VIES integration reference can help teams map the SOAP concepts to application behavior.
What VIES Does Not Tell You
A green VIES response is narrower than many checkout and procurement systems assume. It confirms that the submitted VAT number is valid according to the relevant registry at the time of the query. It doesn't establish every fact you might need for tax, legal, fraud, or credit decisions.
VIES doesn't provide a universal profile of the trader. Depending on the member state and operation, a positive response may include a registered name and address, but those fields shouldn't be treated as a complete corporate record. The service also doesn't provide an effective VAT rate, entity type, complete historical status, or coverage for non-EU jurisdictions.

The checkVatApprox operation can help with name matching, but only because your request includes a name or address to compare. It doesn't magically verify a trading name, beneficial owner, legal form, or operational activity.
Keep the result model deliberately small:
- Validity: Record valid or invalid, plus technical failure states separately.
- Enrichment: Store returned name and address only when the national response supplies them.
- Scope: Don't infer a rate, exemption category, entity type, or historical status from validity.
- Freshness: Attach the query timestamp and a cache policy to every result.
A VAT number can be valid now and require another check before a later invoice or audit decision. The correct mental model is valid at query time, cached briefly, and re-checked before material reliance, not permanently approved.
Pre-Flight Validation Checklist Before Calling VIES
A VIES request shouldn't be your first validation step. Run local checks while the customer is still typing or immediately after form submission, then queue the remote lookup only for values that can plausibly belong to a supported jurisdiction.
Normalize once, then preserve both forms
Trim outer whitespace and convert letters to uppercase. Keep the cleaned value as the canonical key, but retain the raw input in the audit record so support staff can see whether an Excel export added spaces, a CRM removed a prefix, or a customer entered punctuation.
Next, verify the prefix against your current supported set. Include EL for Greece and account for Northern Ireland's XI identifier in records where that code appears. Don't derive the accepted list from a generic ISO country library and assume it matches VAT conventions.
Apply the country-specific pattern from your format table. The purpose isn't to prove registration. It is to stop malformed input from reaching SOAP and to return a useful validation message without waiting for a remote dependency.
Run the checks in a predictable order
- Trim and uppercase: Normalize outer whitespace and letter casing.
- Extract the prefix: Confirm that the first two characters identify a supported VAT jurisdiction.
- Select the rule: Load the country-specific length and character-class policy.
- Reject obvious junk: Catch spaces inside the body, trailing punctuation, unsupported separators, and impossible lengths.
- Persist the decision: Store raw input, cleaned value, rule version, and local result before queuing VIES.

Character classes need country awareness. Many member states use digit-heavy bodies, while EL and other entries can contain letters in defined positions. Don't collapse the entire EU into one [A-Za-z0-9] rule and call that validation. Cache the normalized ID together with its member-state key, so retries don't repeat parsing work or accidentally send a value with a different country interpretation.
Common Pitfalls Developers Hit in Production
The happy path is a form submission followed by a valid response. Production is dominated by everything around that path.
A timeout isn't an invalid number
A customer submits a well-formed German ID and your SOAP call stalls. If the application treats every non-response as invalid, checkout displays a fraud-like error for a network problem. Use separate connect and read timeouts, retry transient failures with exponential backoff and jitter, and let a background reconciliation job complete checks that couldn't finish synchronously.
Don't promise the checkout that VIES will always respond. The public service is a remote dependency backed by national systems, so your UI needs a degraded mode. Depending on your tax policy, that can mean retaining the customer's declared B2B status, placing the order in review, or delaying an exemption decision rather than applying the wrong treatment.
A single invalid response can be a soft failure
National registry changes and synchronization events can create a temporary mismatch between what a customer expects and what VIES returns. A single invalid result should trigger a controlled retry or review path, not an automatic fraud conclusion.
Store the last-known status with its timestamp and distinguish invalid from service_unavailable, malformed input, and provider faults. Before issuing an invoice that depends on the result, perform a fresh check according to your compliance policy.
Normalization drift creates phantom mismatches
An Excel export may pad a value with spaces. A CRM import may remove the prefix. An ERP may prepend a country code in lowercase even though another integration already stores it. Normalize every source through the same pipeline, compare canonical values, and log the original alongside the cleaned form.
Two less obvious problems deserve explicit tests:
- Duplicate registrations: A holding company can have separate VAT registrations across jurisdictions or business units. Match on the issuing country and VAT identifier, not on a company name alone.
- Greek round-tripping: Preserve
ELthrough storage, API requests, exports, and invoice rendering. Converting it toGRat any boundary will break otherwise valid workflows.
Operational rule: Never let a transport error masquerade as a tax decision.
Direct VIES Versus a Managed Validation Layer
Calling VIES directly gives your team control over the request, response handling, and data path. It also means owning SOAP client behavior, WSDL changes, retry policy, logging, cache design, certificate concerns, and member-state-specific quirks. For a low-volume internal tool, that may be a sensible trade.
A managed layer converts the response into a modern application contract. You typically get normalized JSON, machine-readable errors, retry handling, caching keyed by the normalized VAT ID, and metrics that show which issuing jurisdictions are failing. The trade-off is a provider dependency, a per-lookup cost, and another processor in the data chain, so privacy and retention terms need review.
| Concern | Direct VIES | Managed Wrapper |
|---|---|---|
| Protocol | SOAP client and WSDL handling remain yours | REST or SDK interface usually hides SOAP |
| Reliability | You build retries, timeouts, and degraded states | Provider may include retry and outage handling |
| Caching | You design storage, invalidation, and freshness | Caching may be built in or configurable |
| Observability | You collect and normalize member-state errors | Aggregated metrics can simplify diagnosis |
| Data control | Fewer third parties receive the identifier | Provider becomes part of the processing chain |
| Cost model | No wrapper lookup fee, but engineering work is yours | Lookup fees and provider-plan limits apply |
For a few hundred checks a month, direct integration can be reasonable if your team accepts VIES downtime and has time to maintain the adapter. At higher or checkout-critical volumes, caching and normalized failures often matter more than the basic lookup feature.
TaxID is one managed option. It validates EU VAT numbers through VIES, performs country-specific format checks before remote calls, returns status and available registration details in JSON, and provides cached responses and standardized errors for application integrations. Compare those behaviors against your required retention, freshness, and outage policies before choosing a provider.
Glossary of VAT and VIES Terms
VAT: Value-added tax, an indirect consumption tax applied through stages of a supply chain. Businesses generally collect it from customers and account for it with the relevant tax authority.
VIES: The VAT Information Exchange System, the European Commission's interface for checking VAT identification numbers against national VAT registries. It returns a validity result and may return registered name and address data.
Reverse charge: A tax mechanism that shifts the VAT accounting responsibility to the buyer in qualifying transactions. A valid VAT number can be part of the evidence required for a cross-border B2B treatment, but validity alone doesn't determine the complete tax outcome.
MS, or Member State: An EU country participating in the VAT framework relevant to the transaction. In code, the member-state value usually routes a request to the correct national registry.
Intra-Community supply: A cross-border supply between VAT-registered parties in different EU member states. VIES exists in part to support confirmation of VAT numbers used in these workflows.
Validation tiers: The two-layer implementation model described in this guide. The first tier checks local syntax and country rules, while the second asks VIES to confirm registry status. The EU VAT number glossary provides a concise reference for terminology used in code comments and finance workflows.
Frequently Asked Questions on EU VAT Numbers
How should I cross-check the legal entity name?
Ask for the VAT identifier and trader name, then use checkVatApprox where appropriate. Compare the returned name with a configurable tolerance because registries can differ in punctuation, abbreviations, and legal suffixes. A name match supports review, but it isn't a substitute for your broader customer or supplier verification process.
What should happen after a VIES failure?
Use exponential backoff with jitter for retryable failures, save the last-known status with its timestamp, and distinguish service unavailability from an invalid response. Don't block checkout on one timeout. Route the transaction through your documented fallback and reconcile the VAT status asynchronously.
Can I accept a non-EU VAT ID?
Some non-EU jurisdictions can issue VAT identifiers that appear in commercial workflows, but VIES is not a universal validator and reverse charge treatment depends on the customer's establishment and the transaction. Check the establishment country and the applicable tax rule separately rather than treating any foreign VAT ID as an EU result.
What belongs in an audit trail?
Store the country code, raw input, normalized value, VIES response, request identifier when available, timestamp, and the validation-rule version that approved the local format. Keep the local decision separate from the remote result so an auditor can see whether a failure came from syntax, registry status, or service availability. The pre-flight checklist above gives you the minimum sequence to implement before the SOAP request leaves your system.
TaxID provides a developer-focused way to validate EU VAT numbers through VIES without making your billing system own every SOAP failure, normalization rule, and cache decision. Visit TaxID to review the API and build resilient VAT checks into checkout, invoicing, or supplier workflows.