Every French company has a SIREN, every one of its sites has a SIRET, and most have an intra-community VAT number built from the SIREN. All three carry check digits, so you can catch most typing errors before you call any service. This tutorial explains each format, shows offline validation code in Python and JavaScript, and then shows how to confirm that a number that passes the check belongs to a real company.
What you'll learn
- What the SIREN, the SIRET and the French VAT number look like, and how they relate
- How their check digits work, and the code to test them offline
- Why a valid format doesn't prove the company exists
- How to confirm the company, by hand or through an API
- The mistakes that cause most bad numbers in forms
The three numbers, and how they fit together
The SIREN identifies the company itself, the legal unit. INSEE defines it as a nine-digit identifier given to each legal unit; the first eight digits have no meaning and the ninth is a check digit. It is given once and never reused. Renault's SIREN is 441 639 465.
The SIRET identifies an establishment, meaning each place where the company operates. INSEE defines it as a 14-digit number in two parts: the SIREN of the legal unit it belongs to, then the NIC, made of a four-digit order number for the establishment and a check digit. Renault's head office is SIRET 441 639 465 00091: the SIREN, then the NIC 00091.
The French VAT number is the company's intra-community VAT identifier: the letters FR, a two-character key, then the SIREN. Renault's is FR63441639465. The key is computed from the SIREN, so a VAT number can be checked against its own SIREN.
The practical consequence: one company has one SIREN and one VAT number, but as many SIRETs as it has sites. A form that asks for "the company number" should say which one it wants.
How the check digits work
The SIREN and the SIRET both use the Luhn algorithm, the same one used for card numbers. Starting from the rightmost digit, double every second digit; when a doubled value is above 9, subtract 9; add everything up. The number is valid when the total is a multiple of 10. For the SIRET, the check runs over all 14 digits, so it also protects the SIREN part.
The VAT key works differently. It is computed from the SIREN with this formula:
key = (12 + 3 × (SIREN mod 97)) mod 97
The result is written on two digits. We checked the formula against real VAT numbers: for Renault, 441 639 465 gives the key 63 (FR63441639465), and for Doctolib, 794 598 813 gives the key 14 (FR14794598813). The European Commission's VIES service is the authoritative place to confirm a VAT number is registered.
Validate offline, in Python
These functions run without any network access. They strip spaces and dots first, because people paste numbers formatted every possible way.
import re
def digits(value: str) -> str:
return re.sub(r"[\s.\-]", "", value)
def luhn_ok(number: str) -> bool:
total = 0
for i, c in enumerate(reversed(number)):
n = int(c) * (2 if i % 2 else 1)
total += n - 9 if n > 9 else n
return total % 10 == 0
def siren_ok(value: str) -> bool:
d = digits(value)
return len(d) == 9 and d.isdigit() and luhn_ok(d)
def siret_ok(value: str) -> bool:
d = digits(value)
return len(d) == 14 and d.isdigit() and luhn_ok(d)
def vat_key(siren: str) -> str:
return f"{(12 + 3 * (int(siren) % 97)) % 97:02d}"
def fr_vat_ok(value: str) -> bool:
v = digits(value).upper()
if not re.fullmatch(r"FR\d{11}", v):
return False
key, siren = v[2:4], v[4:]
return siren_ok(siren) and key == vat_key(siren)
print(siren_ok("441 639 465")) # True
print(siret_ok("441 639 465 00091")) # True
print(fr_vat_ok("FR63441639465")) # True
print(siren_ok("441639465"[:-1] + "6")) # last digit changed: False
Validate offline, in JavaScript
The same rules, for a browser form or a Node service:
const digits = (v) => v.replace(/[\s.\-]/g, "");
function luhnOk(n) {
let total = 0;
[...n].reverse().forEach((c, i) => {
const d = Number(c) * (i % 2 ? 2 : 1);
total += d > 9 ? d - 9 : d;
});
return total % 10 === 0;
}
const sirenOk = (v) => /^\d{9}$/.test(digits(v)) && luhnOk(digits(v));
const siretOk = (v) => /^\d{14}$/.test(digits(v)) && luhnOk(digits(v));
const vatKey = (siren) => String((12 + 3 * (Number(siren) % 97)) % 97).padStart(2, "0");
function frVatOk(v) {
const s = digits(v).toUpperCase();
if (!/^FR\d{11}$/.test(s)) return false;
return sirenOk(s.slice(4)) && s.slice(2, 4) === vatKey(s.slice(4));
}
console.log(siretOk("44163946500091"), frVatOk("FR63441639465")); // true true
Run these checks as the user types and say clearly what's wrong: "a SIREN has 9 digits" is more useful than "invalid input".
A valid format is not a company
Passing the check digit means the number is well formed. It doesn't mean any company holds it, that the company is still active, or that it's the company your user claims to be. A made-up number has roughly a one-in-ten chance of passing a Luhn check by accident.
So treat the offline check as a filter for typing errors, and confirm the number against the official data before you rely on it. Two cases deserve care:
- A number that passes but finds nothing. Some French companies have asked for their data not to be publicly shared; they don't appear in the public directory. Ask the customer for a registration document rather than refusing on the spot.
- A SIRET that fails the check. Don't reject it automatically if your user insists it's right: look it up first. A failed check digit is a strong hint of a typo, but a lookup is the final word.
Confirm the company exists
By hand. Type the SIREN or SIRET into the Annuaire des Entreprises, the State's public directory that brings together INSEE's Sirene and the national register of companies (RNE). It shows the legal name, the status (active or ceased), the head office and the establishments. For background on these sources, read the French company registers explained.
Through an API. Fuentio's API will return the company for a SIREN, SIRET or VAT number, with its source and check date, when it opens. Until then, the offline check above plus a look at the Annuaire des Entreprises covers most needs.
The mistakes behind most bad numbers
A few mistakes cause most bad numbers in forms:
- A SIRET in a SIREN field, or the reverse. Accept both and take the first nine digits as the SIREN when you get fourteen; then validate both.
- The VAT number with spaces or without FR. Normalise before you check: strip spaces, upper-case, then test the pattern.
- Leading zeros lost. Spreadsheets drop the zeros at the start of numbers. Store identifiers as text, never as numbers.
- The head-office SIRET used for every site. If you invoice or deliver to a specific site, ask for that site's SIRET.
- A number copied from an old document. A company can cease, or a site can close, after the document was printed. The check digit can't tell you that; only a lookup can.
Where this fits
Validating numbers is the first step of most company checks: at sign-up, before an invoice, when cleaning a customer file. It's cheap and it removes most errors. The next step is reading what the register says about the company, which is what KYB is about. See what we cover for France and Spain.
Limits. A check digit proves a number is well formed, not that a company holds it or that it's active. Companies that opted out of public diffusion don't appear in the public directory. The VAT key formula confirms a VAT number matches its SIREN, not that the company is registered for VAT: VIES is the authority for that. Not legal or tax advice.
Frequently asked questions
Is the SIRET just the SIREN with five more digits?
Yes: the first nine digits of a SIRET are the company's SIREN, followed by the NIC (four digits for the establishment and one check digit).
Can I compute the VAT number from the SIREN?
You can compute the expected VAT number, FR plus the key plus the SIREN. Whether the company is actually registered for VAT is confirmed by VIES.
Why does a correct-looking SIREN find nothing?
Either it was mistyped in a way the check digit didn't catch, or the company asked not to be publicly listed. Ask for a registration document.
Should I block a form when the check digit fails?
Show a clear message and let the user correct it. If they insist, look the number up before rejecting it.
Sources
- INSEE, definition of the SIREN number (updated 21/10/2025, read on 8 October 2026): insee.fr
- INSEE, definition of the SIRET number (read on 8 October 2026): insee.fr
- Annuaire des Entreprises: annuaire-entreprises.data.gouv.fr
- European Commission, VIES VAT number validation: ec.europa.eu
