npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@codeshark/vat

v0.3.0

Published

Offline VAT number validation (format + checksum) for EU and selected other countries

Readme

@codeshark/vat

Offline VAT number validation for the EU and a few other countries. It checks format and checksum, has no dependencies, and makes no network calls.

It's a drop-in replacement for jsvat, which was archived in 2026-03.

import { checkVAT } from "@codeshark/vat";

checkVAT("BE0411905847").isValid; // true
checkVAT("BE0411905848").isValid; // false, bad checksum

A valid result means the number is well formed, not that it's registered. Use VIES for that.

Why use it

  • Fast. About 190 ns per call, 7× faster than jsvat 2.5.4 on valid numbers and 40× faster on input that matches no country. Run pnpm bench to measure it yourself.
  • Current rules. It follows recent national formats, such as Belgian numbers starting with 1 (issued since 2023), and checks Italian office codes and French letter keys. Coming from jsvat? See what changed.
  • Tested against shared vectors. The test cases are plain JSON in test-vectors/, so ports in other languages can reuse them.

Install

npm install @codeshark/vat

ESM only, with TypeScript types included. CommonJS consumers on Node 20.19+ can require("@codeshark/vat") directly.

Coming from jsvat? Change the import. Exports and the result shape match jsvat 2.5.4.

- import { checkVAT, countries } from "jsvat";
+ import { checkVAT, countries } from "@codeshark/vat";

Usage

checkVAT(vat: string, countries?: Country[], options?: { assumeCountry?: Country }): VatCheckResult
import { checkVAT, belgium } from "@codeshark/vat";

checkVAT("BE0411905847"); // checks against all countries
checkVAT("BE0411905847", [belgium]); // only Belgium
checkVAT("0411905847", undefined, { assumeCountry: belgium }); // number has no prefix

countries defaults to all supported countries. assumeCountry applies only when the number doesn't match a format as typed. It must be in countries, or checkVAT throws a TypeError.

interface VatCheckResult {
  value?: string; // uppercased, with whitespace and . , / - removed
  isValid: boolean; // format and checksum both pass
  isValidFormat: boolean;
  isSupportedCountry: boolean;
  country?: {
    name: string;
    isoCode: { short: string; long: string; numeric: string };
  };
}

When the format matches, value is the official form:

| Country | Input | value | | ----------- | -------------------------------------- | ------------------ | | Belgium | BE411905847 | BE0411905847 | | Greece | EL94051189 | EL094051189 | | Netherlands | NL4495445B01 | NL004495445B01 | | Norway | NO974760673 | NO974760673MVA | | Switzerland | CHE272990183, CHE272990183TVA, ... | CHE272990183MWST |

Supported countries

Andorra, Austria, Belgium, Brazil, Bulgaria, Croatia, Cyprus, Czech Republic, Denmark, Estonia, Europe (EU), Finland, France, Germany, Greece, Hungary, Ireland, Italy, Latvia, Lithuania, Luxembourg, Malta, Netherlands, Norway, Poland, Portugal, Romania, Russia, Serbia, Slovakia, Slovenia, Spain, Sweden, Switzerland, United Kingdom (GB, and XI for Northern Ireland).

Each country is exported by its camelCase name, such as belgium or unitedKingdom. Note czechRepublic and slovakiaRepublic. countries holds them all.

EU numbers are issued to non-EU businesses under the non-Union OSS scheme. They have no public checksum, so only the format (EU plus 9 digits) is checked.

Differences from jsvat

Accepts numbers jsvat rejects:

  • Belgian numbers starting with 1, issued since 2023 (BE1006023325).
  • Greek and Dutch numbers missing leading zeros (EL94051189, NL4495445B01).
  • Andorran numbers with any final control letter (ADL708585T).
  • Digit-only Brazilian numbers. jsvat treats 02.061.065/0001-72 as Andorran and rejects it.
  • XI, as the United Kingdom.

Rejects numbers jsvat accepts:

  • Polish numbers that can't have a valid check digit (PL1234567890, PL0000000000).
  • Andorran F, A and L numbers outside their official ranges (ADA000000A).
  • French numbers with letter keys and a bad checksum (FRXX433138302).
  • Italian numbers without a known office code: 001–100, 120, 121, 888 or 999 (jsvat allowed up to 201).

Other changes:

  • The countries list is optional and defaults to all countries. jsvat reports every number as invalid without it.
  • value is the official form for Belgium, Greece, the Netherlands, Norway and Switzerland.
  • Commas count as separators.

Development

  • pnpm test: Vitest over test-vectors/*.json
  • pnpm typecheck: tsc, no emit
  • pnpm build: tsc -p tsconfig.build.json → dist/ (per-file ESM + .d.ts)
  • pnpm lint / pnpm lint:fix: Biome (also runs on staged files via husky + lint-staged)
  • pnpm bench: ns per call for a few input types

Each test-vectors/<country>.json holds valid, validOnlyByFormat and invalid lists, converted from jsvat's test/countries_vat_lists.

License

MIT. Derived from jsvat 2.5.4 by Sergei Panfilov. See LICENSE and LICENSE.jsvat.