Vat.Net 0.2.0

dotnet add package Vat.Net --version 0.2.0
                    
NuGet\Install-Package Vat.Net -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Vat.Net" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Vat.Net" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Vat.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Vat.Net --version 0.2.0
                    
#r "nuget: Vat.Net, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Vat.Net@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Vat.Net&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Vat.Net&version=0.2.0
                    
Install as a Cake Tool

Vat.NET

Validate European Union and United Kingdom VAT registration numbers offline: per-country format and check-digit verification without calling VIES. Zero external dependencies.

The VIES web service is the only way to confirm a VAT number is actually registered, and Vat.NET does not replace it. But VIES is a network call: it goes down, it rate-limits, it is unreachable from a background job with no outbound internet, and it cannot run inside a unit test. Most of the time what you actually need before you ever call VIES, or instead of calling it for a cheap first pass, is to know whether a number is even well-formed: right length, right character set, and where the country defines one, a correct check digit. Vat.NET answers that offline, synchronously, with no dependency on a third-party service being up.

There is no actively maintained, dependency-free .NET package that does this today across the full EU membership plus the UK with per-country checksums. Vat.NET is that package.

Install

dotnet add package Vat.Net

Usage

Infer the country from the number's own prefix:

using Vat;

VatNumberValidator.IsValid("DE136695976");        // true
VatNumberValidator.IsValid("DE 136.695.976");      // true, spaces and dots are ignored
VatNumberValidator.IsValid("DE136695978");         // false, bad check digit

Validate against a country you already know, and inspect why a number failed:

using Vat;

var result = VatNumberValidator.Validate("FR", "23334175221");

result.IsValid;             // true
result.CountryCode;         // "FR"
result.NormalizedNumber;    // "23334175221"
result.IsChecksumVerified;  // true, France's key algorithm ran and passed

A failed validation reports which stage rejected it:

using Vat;

var result = VatNumberValidator.Validate("IE6433435E");

result.IsValid;    // false
result.Failure;    // VatValidationFailure.InvalidChecksum

Failure is one of EmptyInput, UnknownCountry, InvalidFormat or InvalidChecksum (None on success).

Northern Ireland (XI)

Since the post-Brexit Northern Ireland Protocol, Northern Irish businesses trading goods with the EU use VAT numbers prefixed XI instead of GB. An XI number has the identical structure and check digit algorithm as a UK number, so Vat.NET validates XI with the exact same rule as GB (one shared implementation, so the two can never drift). A valid UK number stays valid when its prefix is swapped to XI; the result's CountryCode is reported as XI.

using Vat;

VatNumberValidator.IsValid("XI980780684");   // true, same rule as GB980780684
VatNumberValidator.Validate("XI980780684").CountryCode;   // "XI"

XI is the WTO/VAT prefix for Northern Ireland; it is not an ISO 3166-1 alpha-2 country code, and is surfaced as the country code exactly as Greece's VAT prefix EL is.

Normalization

Input is normalized by stripping spaces, dots, and (for the single-argument overload) the number's own leading two-letter country prefix, before format and checksum rules run. VatNumberValidator.Validate("DE", "DE 136.695.976") and VatNumberValidator.Validate("DE136695976") both resolve to the same normalized number. Separators other than spaces and dots (hyphens, slashes) are not stripped; if your source data uses them, remove them before calling in.

Checksum-verified vs format-only

Twenty-five of the 28 supported countries have their check digit or checksum algorithm implemented and verified. For three countries, one specific sub-format is deliberately left format-only rather than guessed:

Country Coverage
Austria, Belgium, Croatia, Cyprus, Denmark, Estonia, Finland, France, Germany, Greece, Hungary, Ireland, Italy, Lithuania, Luxembourg, Malta, Netherlands, Poland, Portugal, Romania, Slovakia, Slovenia, Spain, Sweden, United Kingdom, Northern Ireland Checksum-verified
Bulgaria Checksum-verified for the 9-digit legal-entity form. The 10-digit form (physical persons, foreigners and others) is accepted on format alone: it can validly derive from either a general weighted formula or the holder's national identity number, and this package does not implement national identity number validation.
Czechia Checksum-verified for the 8-digit legal-entity form and the 9-digit special form starting with "6". Other 9 and 10-digit numbers encode a birth number (rodné číslo) whose validity depends on parsing a real calendar date, which this package does not implement, so they are accepted on format alone.
Latvia Checksum-verified for legal entities (first digit greater than 3). Natural-person numbers mirror a personal code whose check digit formula has no independently confirmed primary source, so they are accepted on format alone rather than guessed.

VatValidationResult.IsChecksumVerified tells you, per call, whether the specific number you passed in was actually checksum-checked or only format-checked, so you never have to guess which path a given result took.

Every implemented checksum (ISO 7064 Mod 11-10 for Germany and Croatia, the UK's 97-minus modulus including its restarted-number allowance, France's mod-97 key over the SIREN, Italy's Luhn check, and the rest) is a direct, line-by-line port of the corresponding algorithm in python-stdnum, an actively maintained, widely used open-source reference implementation, cross-checked by hand against its embedded published test numbers during development. The full fixture table, including every valid number and its corrupted-checksum counterpart, is in tests/Vat.Net.Tests/VatFixtures.cs.

Dependencies and AOT

Zero runtime NuGet dependencies. Built entirely on the .NET base class library: System.Text.RegularExpressions (source-generated, compile-time regex, no reflection) and System.Numerics.BigInteger for the one checksum (the Dutch alternate numbering scheme) that needs arbitrary-precision arithmetic. No reflection, no dynamic code generation, no I/O. This makes Vat.NET compatible with Native AOT publishing and trimming out of the box.

License

MIT. See LICENSE.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0 52 8/21/2026
0.1.0 84 8/12/2026