Netherlands BSN check
Enter 12345678 and get check digit 2, so the full BSN is 123456782; or paste a nine-digit number to see whether it passes the Dutch eleven-test. Handy for sign-up forms and payroll imports. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Number
- 12345678
- Calculation mode
- Compute
- Input
- 12345678
- Check digit
- 2
- Bsn
- 123456782
The Dutch BSN (Burgerservicenummer) is the citizen service number used across tax, healthcare, payroll, banking, and government forms in the Netherlands. It is a nine-digit identifier whose last digit is a check digit derived from a fixed weighted sum known as the eleven-test or elfproef. Eight digits identify the registration; the ninth is chosen so that nine times the first digit plus eight times the second, continuing down through two times the eighth, minus the ninth, is divisible by eleven. This capability computes that final digit from a pure eight-digit base, or validates a complete nine-digit BSN and reports whether the stored digit matches the recomputed value.
How the Dutch BSN eleven-test works
A modern BSN is always nine decimal digits when written without spaces or punctuation. The first eight form the base registration; the ninth is the check digit. To obtain that digit, multiply the eight base digits by the descending weights nine through two, sum the products, and take the sum modulo eleven.
The remainder is the check digit when it lies between zero and nine. If the remainder is ten, no single check digit exists for that base and the eight-digit string cannot be completed into a valid BSN under the official rule. Validation multiplies all nine digits by weights nine, eight, seven, six, five, four, three, two, and minus one respectively, then requires the weighted sum to be divisible by eleven with no leftover remainder.
Equivalently, you recompute the expected ninth digit from the first eight and compare it to the digit that was submitted. Historical eight-digit BSNs are usually treated as nine-digit values with a leading zero before applying the same weights; this tool expects you to supply the leading zero yourself when validating such numbers so length rules stay explicit.
Where BSN check digits fit real product workflows
Dutch fintech, insurtech, and marketplace onboarding flows often ask for a BSN early; validating the eleven-test on blur reduces failed submissions and support tickets without calling a government registry for every keystroke. Payroll and HR systems import employee CSVs and should quarantine rows whose ninth digit no longer matches, which catches both human edits and off-by-one bugs in upstream generators.
Do not treat a passing eleven-test as proof that the person exists in Dutch population systems, that the number is active, or that you are allowed to process the BSN under GDPR and Dutch privacy law—it only proves the nine-digit string is arithmetically well formed under the BSN rule, the same honesty bar you apply to any national-id checksum tool. Always minimize retention, encrypt at rest, and process BSN only when a lawful purpose exists.
What you can do with it
Audit BSN columns in bulk exports
Batch-validate every BSN in a payroll CSV or ERP extract and quarantine rows whose check digit no longer matches the recomputed eleven-test value.
FAQ
What is the Dutch BSN check digit?
It is the ninth digit of a Burgerservicenummer, computed from the first eight with the official eleven-test weights so single-digit typos and many transcription errors are far more likely to fail validation than to look like another registration.
What happens with letters, hyphens, or wrong lengths?
Failed validation tasks are not billed. Strip spaces or punctuation in your client before calling.
Is the Netherlands BSN check tool free?
The browser tool is free and runs locally.
How do I check an old eight-digit BSN?
Add a leading zero yourself so the number has nine digits, then validate it as usual. The tool does not pad short numbers on its own, so length mistakes never slip through unnoticed.
Does a BSN that passes the eleven-test belong to a real person?
Not necessarily. The test only shows that the digits are consistent with each other. It does not prove that the person exists in Dutch records, that the number is active, or that you may process it.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/enc/bsn-netherlands \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"number":"12345678"}'const res = await fetch("https://api.kit.forhosting.com/enc/bsn-netherlands", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"number": "12345678"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/bsn-netherlands",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"number": "12345678"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/bsn-netherlands", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"number":"12345678"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"number":"12345678"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/bsn-netherlands", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"number": "12345678"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.bsn_netherlands",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Non-numeric characters, wrong lengths, empty input, and bases that yield remainder ten (no single-digit check possible) are rejected with a clear invalid_input error. Run it free in the browser or call the KIT API; both paths share the same pure arithmetic with no network round-trip and no stored population registries.
How the Dutch BSN eleven-test works
Because the algorithm is pure integer modular arithmetic with fixed weights, the same eight digits always produce the same check digit on every platform—browser, Worker, or offline test harness—which is why the capability ships as a tier-A parse engine rather than a model call.
How to compute the check digit or validate a full BSN
Send a number field that contains only characters zero through nine. Mode validate expects exactly nine digits. Empty strings, missing number, invalid mode values, and wrong lengths (for example seven or ten digits) fail before any weighted sum runs and are not billed. Spaces, dots, hyphens, letters, and decimal points are rejected as non-numeric input with invalid_input so a form never accepts a silently cleaned value—strip formatting in your client if users paste masked numbers. Mode compute is the default: provide exactly eight base digits; the engine returns check_digit as a one-character string, bsn as the full nine-digit code, sum_base as the intermediate weighted sum of the eight digits, length nine, and the algorithm label. If the eight-digit base yields remainder ten, compute fails with invalid_input rather than inventing a two-digit or null digit. The response reports valid true only when the trailing digit matches the recomputed expected_check_digit and the full weighted sum is divisible by eleven; it always includes base (the first eight digits), check_digit as submitted, expected_check_digit when a legal base exists, weighted_sum, and the canonical bsn built from base plus expected digit. That shape makes it easy to show “you typed X, expected Y” in a KYC or HR UI without a second request. Because the path is pure parse with no clock, random source, or network, the same input always yields the same JSON on the free browser tool and on the API. At $0.002 per successful request you can protect bulk CRM imports, partner file audits, and form gates without negotiating a custom tier.
Where BSN check digits fit real product workflows
Healthcare portals and pharmacy systems that store BSN as a patient key can block proceed until valid is true and show expected_check_digit when the digit is wrong. Data-quality jobs recompute expected_check_digit for every BSN column in an export and flag mismatches before they reach billing or fiscal reporting.
Integration use cases
Complete eight base digits for fixtures and forms
Take an eight-digit base from a test plan or partial record, call compute mode, and store or display the full nine-digit bsn with the check digit appended.
Validate typed or imported BSNs at entry
When a signup form, CRM import, or partner API submits nine digits, call validate mode and block storage when valid is false, showing expected_check_digit to fix a mistype.
Technical questions
How do I compute a BSN check digit with this API?
POST with number set to exactly eight digits and mode compute (or omit mode). The response includes check_digit and bsn (the full nine-digit code). Bases with remainder ten fail with invalid_input.
How do I validate a full nine-digit BSN?
POST with the nine-digit string and mode validate. The response includes valid, check_digit, expected_check_digit, base, weighted_sum, and the canonical bsn.