Sweden personnummer check digit
The nine digits 811228987, a birth date plus serial, get the Luhn check digit 4, giving the personnummer 8112289874. Enter nine digits to complete a Swedish personal identity number, or ten or twelve digits to confirm its last digit. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Number
- 811228987
- Calculation mode
- Compute
- Input
- 811228987
- Date
- 811228
- Serial
- 987
The Swedish personnummer (personal identity number) is the national civil identifier used for taxation, healthcare, banking, employment, and most public-facing forms in Sweden. A twelve-digit form prefixes the century (YYYYMMDD plus serial and check). The check digit is not random decoration: it is produced by the Luhn algorithm over the first nine digits of the short form so that a single mistyped digit or a swapped pair is usually rejected before the number is stored or matched. This capability implements that checksum only. Compute mode accepts exactly nine digits—date plus serial without the check—and returns the Luhn digit plus the completed ten-digit string. Validate mode accepts ten or twelve digits (optional hyphens or plus separators) and reports whether the trailing digit matches the recomputed expected value.
How the Swedish personnummer check digit is calculated
From the left, counting positions one through nine, every odd position is doubled; if twice a digit is greater than nine, nine is subtracted (equivalently the two digits of the product are summed). Even positions contribute the digit unchanged. The nine weighted values are added; the check digit is ten minus that sum modulo ten, modulo ten again, so that appending the check digit makes the ten-digit short form Luhn-consistent.
Coordination numbers (samordningsnummer) use day-of-month plus sixty and still use the same Luhn rule over the nine body digits; this tool does not invent a different algorithm for them. The algorithm is deterministic and local: no population registry call, no clock, and no randomness. Compared with generic card Luhn or IMEI Luhn tools, the search intent here is narrow: people who need a Sweden personnummer check digit calculator for date-plus-serial bases or a ten- or twelve-digit Swedish personal number checker, not a payment or device tool.
Where personnummer check digits fit real Swedish workflows
Banks and fintechs validate ten- or twelve-digit personnummer values at account opening so a single transposition does not create a phantom customer and a rejected KYC record. ETL jobs that load Swedish customer or employee master files walk every personnummer column in a CSV or XML feed, call validate mode, and quarantine rows where valid is false—catching both human edits and off-by-one bugs in generators.
Municipal and school systems often accept both hyphenated and compact forms; stripping spaces, hyphens, and plus before the digit check keeps the contract simple without inventing a second algorithm. Do not treat a passing personnummer check as proof that the holder is alive in the population register, has a Swedish personal identity card, or is authorized for a service; it only proves the Luhn digit is consistent with the date and serial under the official Swedish personnummer weights.
What you can do with it
Audit personnummer columns in master data
Batch-validate every personnummer in a CRM, EHR, or payroll CSV and quarantine rows whose check digit no longer matches the recomputed expected value.
FAQ
What is a Swedish personnummer check digit?
It is the tenth digit of the short Swedish personal identity number, computed with the Luhn algorithm over the six-digit birth date and three-digit serial so typing and scanning errors are usually caught before the number is stored.
Is the personnummer check digit tool free?
The browser tool is free and runs locally.
How is the personnummer check digit calculated?
Take the nine digits of birth date and serial and double every digit in an odd position from the left, subtracting nine from any result above nine. Add everything; the check digit is the one that brings the total to a multiple of ten. For 811228987 it is 4.
Does the twelve-digit form change the check digit?
No. In the twelve-digit form the first two digits only show the century, for display and sorting. The check digit is still calculated from the same nine digits as in the short form.
Does it work for coordination numbers?
Yes. A coordination number, or samordningsnummer, adds sixty to the day of birth but uses exactly the same Luhn rule over its nine digits, so the tool calculates and checks it the same way.
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/personnummer-sweden \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"number":"811228987"}'const res = await fetch("https://api.kit.forhosting.com/enc/personnummer-sweden", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"number": "811228987"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/personnummer-sweden",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"number": "811228987"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/personnummer-sweden", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"number":"811228987"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"number":"811228987"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/personnummer-sweden", 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": "811228987"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.personnummer_sweden",
"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
In its short form it is ten digits: six digits for the birth date as year-month-day (YYMMDD), three digits for a serial assigned within that day, and one trailing check digit. Non-numeric bodies and wrong lengths fail with invalid_input instead of silent stripping. The same pure arithmetic runs free in the browser and at the published API price, with no registry lookup and no claim that a valid checksum means the person is living, registered, or entitled to any service.
How the Swedish personnummer check digit is calculated
Under the Swedish Tax Agency (Skatteverket) rules, the personnummer check digit is a Luhn mod-10 value computed on nine digits: the six-digit birth date YYMMDD followed by the three-digit serial. Validation recomputes the expected digit from the nine-digit payload and compares it to the last digit of the submitted number. For the twelve-digit century form YYYYMMDDNNNC, the Luhn payload is still the nine digits YYMMDDNNN—the century digits are display metadata for age and sorting, not part of the checksum weights.
Input contract, modes, and error behaviour
Send a number field that contains the personnummer body. Wrong length is an explicit error that names the mode and the length you sent—nine for compute, ten or twelve for validate—so client forms can show a precise message without guessing. Empty strings, missing number, and invalid mode values fail before any Luhn sum runs and are not billed. A well-formed string that simply has the wrong check digit returns valid false without throwing. Spaces, hyphens, and plus signs are stripped so common Swedish display forms such as 811228-9874 or 19811228-9874 are accepted after normalization; other punctuation and letters are rejected as non-numeric input with invalid_input so a silently stripped value never reaches storage. Mode compute is the default: the engine requires exactly nine digits, returns check_digit as a one-character string, returns with_check as the ten-digit short personnummer you can print or persist, and also returns date (YYMMDD) and serial (three digits) for audit trails. Mode validate accepts exactly ten digits (YYMMDDNNNC) or twelve digits (YYYYMMDDNNNC); the response reports valid true when the trailing digit matches the recomputed expected_check_digit, and always includes payload (the nine Luhn digits), check_digit, expected_check_digit, date, serial, form ("10" or "12"), and length. For twelve-digit input the response also includes century and full_date (YYYYMMDD) without treating century as part of the Luhn sum. Alias keys such as personnummer, pnr, digits, and code are accepted for the same payload field so integrations that already speak Swedish field names do not need a rename. Because the path is pure parse with no clock, random source, or network, the same JSON body always yields the same JSON result on the free browser tool and on the API at $0.002 per successful request.
Where personnummer check digits fit real Swedish workflows
Healthcare portals and pharmacy systems recompute expected_check_digit when a clinic reads a number over the phone or pastes it from a scanned card, catching mistypes before a journal entry or prescription is filed. Employers and payroll vendors complete nine-digit bases in sandboxes with compute mode, then store with_check in test employees that must look like production identifiers.
Integration use cases
Complete a 9-digit personnummer base for test fixtures
Call compute mode with YYMMDD plus three serial digits, store with_check, and use the ten-digit personnummer in sandbox KYC, payroll, or healthcare test records.
Validate typed or imported Swedish personal numbers
When a form, bank file, or HR feed submits ten or twelve digits, call validate mode and block enrollment when valid is false, showing expected_check_digit to help correct a single mistype.
Technical questions
How do I compute a personnummer check digit with this API?
POST with number set to exactly nine digits (YYMMDD plus serial) and mode compute (or omit mode). The response includes check_digit and with_check (the full ten-digit short form).
How do I validate a full ten- or twelve-digit personnummer?
POST with the digit string (optional hyphens or plus) and mode validate. The response includes valid, check_digit, expected_check_digit, and payload (the nine Luhn digits).
What happens with wrong length, letters, or odd punctuation?
After stripping spaces, hyphens, and plus signs, non-numeric input and lengths other than nine (compute) or ten/twelve (validate) are rejected with invalid_input. Failed validation tasks are not billed.