![require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages](https://cdn.sanity.io/images/cgdhsj6q/production/be8ab80c8efa5907bc341c6fefe9aa20d239d890-1600x1097.png?w=400&fit=max&auto=format)
Security News
require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
International sales tax calculator for Node (offline, except for VAT number validation). Tax rates are kept up-to-date.
International sales tax calculator for Node (offline, except for VAT number validation). Tax rates are kept up-to-date.
You may use it to calculate VAT rates for countries in the European Union (VAT MOSS), GST in Canada, or get VAT for countries such as China, or even Hong Kong (which has no VAT).
![]() |
Crisp |
👋 You use sales-tax and you want to be listed there? Contact me!
Include sales-tax
in your package.json
dependencies.
Alternatively, you can run npm install sales-tax --save
.
This module may be used to acquire the billable VAT percentage for a given customer. You may also use it directly to process the total amount including VAT you should bill; and even to validate a customer's VAT number.
:red_circle: Important: in order to fetch the sales tax for a customer, you need to know their country. The country must be passed to all module methods, formatted as ISO ALPHA-2 (eg. France is FR, United States is US).
Import the module in your code:
var SalesTax = require("sales-tax");
Check some countries for sales tax (returns true
or false
):
var franceHasSalesTax = SalesTax.hasSalesTax("FR") // franceHasSalesTax === true
var brazilHasSalesTax = SalesTax.hasSalesTax("BR") // brazilHasSalesTax === true
var hongKongHasSalesTax = SalesTax.hasSalesTax("HK") // hongKongHasSalesTax === false
:fr: Given a French customer VAT number (eg. here SAS CLEVER CLOUD
with VAT number FR 87524172699
):
SalesTax.getSalesTax("FR", "87524172699")
.then((tax) => {
// This customer is VAT-exempt (as it is a business)
/* tax ===
{
type : "vat",
rate : 0.00,
exempt : true
}
*/
});
Note: Clever-Cloud is a real living business from France, check their website there.
:latvia: Given a Latvian customer without any VAT number (eg. a physical person):
SalesTax.getSalesTax("LV")
.then((tax) => {
// This customer has to pay 21% VAT (as it is a physical person)
/* tax ===
{
type : "vat",
rate : 0.21,
exempt : false
}
*/
});
:hong_kong: Given an Hong Kong-based customer (eg. a physical person):
SalesTax.getSalesTax("HK")
.then((tax) => {
// Hong Kong has no VAT
/* tax ===
{
type : "none",
rate : 0.00,
exempt : true
}
*/
});
:es: Given a Spanish customer who provided an invalid VAT number (eg. a rogue individual):
SalesTax.getSalesTax("ES", "12345523")
.then((tax) => {
// This customer has to pay 21% VAT (VAT number could not be authenticated against the European Commission API)
/* tax ===
{
type : "vat",
rate : 0.21,
exempt : false
}
*/
});
:estonia: Given an Estonian customer without any VAT number, buying for 100.00€ of goods (eg. a physical person):
SalesTax.getAmountWithSalesTax("EE", 100.00)
.then((amountWithTax) => {
// This customer has to pay 20% VAT
/* amountWithTax ===
{
type : "vat",
rate : 0.20,
exempt : false,
price : 100.00,
total : 120.00
}
*/
});
:fr: Given a French customer VAT number (eg. here SAS CLEVER CLOUD
with VAT number FR 87524172699
):
SalesTax.validateTaxNumber("FR", "87524172699")
.then((isValid) => {
// isValid === true
});
:latvia: Given a Latvian customer without any VAT number (eg. a physical person):
SalesTax.validateTaxNumber("LV")
.then((isValid) => {
// isValid === false
});
:es: Given a Spanish customer who provided an invalid VAT number (eg. a rogue individual):
SalesTax.validateTaxNumber("ES", "12345523")
.then((isValid) => {
// isValid === false
});
:fr: Given a French customer VAT number (eg. here SAS CLEVER CLOUD
with VAT number FR 87524172699
):
SalesTax.isTaxExempt("FR", "87524172699")
.then((isTaxExempt) => {
// isTaxExempt === true
});
:morocco: Given a Morocco-based customer:
SalesTax.isTaxExempt("MA")
.then((isTaxExempt) => {
// isTaxExempt === false
});
:hong_kong: Given an Hong Kong-based customer:
SalesTax.isTaxExempt("HK")
.then((isTaxExempt) => {
// isTaxExempt === true
});
Disable tax number validation (disable hitting against external APIs and consider all tax numbers as valid):
SalesTax.toggleEnabledTaxNumberValidation(false)
Enable tax number validation (enabled by default — use only if you disabled it previously):
SalesTax.toggleEnabledTaxNumberValidation(true)
The offline tax data is pulled from VAT, GST and sales tax rates — ey.com.
It is kept up-to-date with the year-by-year tax changes worldwide.
Some countries have multiple sales tax, eg. Brazil. In those cases, the returned sales tax is the one on services. Indeed, I consider most users of this module use it for their SaaS business — in other words, service businesses.
For now, this module only supports tax number (VAT number) validation for European countries.
European VAT numbers are validated against the official ec.europa.eu
API, which return whether a given VAT number exists or not. This helps you ensure a customer-provided VAT number is valid (ie. you don't have to bill VAT for this customer).
You can manually check a VAT number on VIES VAT number validation.
FAQs
International sales tax calculator for Node (offline, but provides optional online VAT number fraud check). Tax rates are kept up-to-date.
The npm package sales-tax receives a total of 4,507 weekly downloads. As such, sales-tax popularity was classified as popular.
We found that sales-tax demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.