Romanian CNP check digit
Enter 180010122114 and get check digit 4, so the full CNP is 1800101221144; or paste all thirteen digits to see whether the last one fits the official weighting. Useful in HR, payroll and customer onboarding. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Cnp
- 180010122114
- Calculation mode
- Compute
- Input
- 180010122114
- Check digit
- 4
- With check
- 1800101221144
- Formatted
- 1-800101-22-114-4
The Romanian personal numeric code (CNP, Cod Numeric Personal) is a thirteen-digit identifier used on civil status records, employment contracts, tax filings, banking KYC, and public-service forms across Romania. The last digit is a check digit derived from a fixed weighting of the first twelve digits under the official modular rule published with the CNP layout. A single mistyped digit or a swapped pair often breaks that checksum, so validating the CNP before saving a HR record, opening a customer profile, or accepting a partner file catches many keying errors early.
What the Romanian CNP check digit is and how the weights work
A CNP encodes sex and century, date of birth, county of issuance, and a serial number in a fixed thirteen-digit layout used by Romanian administrative, fiscal, and commercial systems. Forms sometimes insert spaces or hyphens for readability, but the underlying value is always thirteen decimal digits. The first twelve digits form the body; the thirteenth is completely determined by a public check algorithm and is not chosen freely.
The official weighting multiplies those twelve digits, left to right, by the constant sequence two, seven, nine, one, four, six, three, five, eight, two, seven, and nine — the weight string 279146358279. The products are summed, and the remainder of that sum modulo eleven is the candidate check digit. When the remainder is a value from zero through nine, that value is the check digit and completes a well-formed CNP string.
When the remainder is ten, the check digit is defined as one, not ten, so every twelve-digit body maps to exactly one trailing digit zero through nine. Compared with Luhn mod-ten used on payment cards, the CNP scheme uses a fixed left-to-right weight vector and modulo eleven with a special rule for remainder ten, so you must not reuse a Luhn validator on Romanian personal ID fields.
Compared with Polish NIP weights or Norwegian fødselsnummer double mod-eleven digits, the Romanian CNP rule is specific to this thirteen-digit layout and this twelve-position weight string. Knowing which scheme you need avoids false confidence when a general check-digit utility accepts a digit string that is not a well-formed CNP. This tool implements the standard weighting on pure digits after optional space and hyphen stripping.
It does not query government portals, prove that a person exists, decode gender or county, or assign legal status — only that the digit string is consistent under the published check algorithm.
Where Romanian CNP check digits fit HR, banking, and administrative workflows
Human-resources and payroll systems store a employee CNP on every legal Romanian employment document; a single mistyped digit during onboarding can fail subsequent social-security or tax submissions. Banking and fintech KYC flows that collect a Romanian personal numeric code can recompute the check digit without calling an external registry, filtering OCR noise and partial captures early. Product teams that already expose general Luhn or ISO 7064 check tools should still use this CNP-specific capability for Romanian personal ID fields so weights, length bounds, and remainder-ten handling match the domain.
Educational and SEO landings that rank for phrases such as romanian cnp check digit or romania cnp validator need a live free tool whose browser path matches automation so tutorial screenshots stay accurate. Do not treat a passing CNP check digit as proof that the person is correctly identified, alive, authorized, or present in any official registry — it only proves the digit string is consistent under the Romanian CNP check algorithm.
What you can do with it
Audit CNP columns in partner and payroll files
Batch-validate every CNP in a CSV import and quarantine rows whose check digit no longer matches the recomputed expected value.
FAQ
How is the Romanian CNP check digit calculated?
Multiply the first twelve digits by the weights 2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, and 9 (the constant string 279146358279), sum the products, and take the sum modulo 11. If the remainder is 0–9 that is the check digit; if it is 10 the check digit is 1.
What is the difference between compute and validate modes?
Compute takes twelve digits and returns the check digit and full thirteen-digit CNP. Validate takes thirteen digits including the trailing digit and returns whether it matches the recomputed check digit.
What happens if the check digit is wrong?
In validate mode the response still includes the expected digit, and valid is false.
What happens when the weighted sum leaves a remainder of 10?
The check digit becomes 1, not 10. That special rule is why every twelve-digit body has exactly one trailing digit between 0 and 9.
Does the tool read the birth date or county from a CNP?
No. It only checks that the digits are consistent with the published check rule. It does not decode sex, birth date or county, query government portals or prove that the person exists.
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/cnp-romania \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"cnp":"180010122114"}'const res = await fetch("https://api.kit.forhosting.com/enc/cnp-romania", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"cnp": "180010122114"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/cnp-romania",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"cnp": "180010122114"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/cnp-romania", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"cnp":"180010122114"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"cnp":"180010122114"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/cnp-romania", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"cnp": "180010122114"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.cnp_romania",
"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
This capability computes the Romanian CNP check digit for a twelve-digit payload (with or without common spaces and hyphens), or validates a full thirteen-digit number that already includes the trailing digit, and it reports bad input instead of silently inventing a digit. Use it free in the browser or call the KIT API at the published price; both paths run the same deterministic arithmetic with no network lookup and no registry of real persons.
How to compute a check digit or validate a full CNP
Send a cnp field that contains digits zero through nine, optionally separated by spaces or hyphens. Mode validate expects a complete thirteen-digit number including the trailing check digit (for example 1800101221144 or a hyphenated thirteen-digit form). Empty strings, missing cnp, invalid mode values, and wrong lengths fail before any weighted sum runs and are not billed. Letters, other punctuation, double hyphens, or leading or trailing hyphens are rejected as malformed input with invalid_input so you never accept a silently cleaned value. Mode compute is the default: provide exactly twelve digits without the check digit (for example 180010122114), and the engine returns check_digit as a one-character string, with_check as the full thirteen-digit string including that digit, and formatted as a readable S-YYMMDD-JJ-NNN-C grouping. The response reports valid true when the recomputed check digit matches the last digit, and always includes check_digit, expected_check_digit, payload without the last digit, weighted_sum_mod11, and formatted for consistent display. 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 gate bulk HR imports, onboarding forms, and ETL jobs without negotiating a custom tier. Prefer compute when you assemble a CNP from a known twelve-digit body; prefer validate when a user, partner file, or scanned label supplies a full number and you need a boolean gate before a registry or master-data lookup.
Where Romanian CNP check digits fit HR, banking, and administrative workflows
Validate mode at entry blocks the save when valid is false and can show expected_check_digit so the clerk corrects the form before the record is written. Insurance, healthcare, and public-service portals receive CNPs from forms and partner files where a wrong trailing digit would reject a whole batch; a deterministic oracle that returns valid and with_check lets importers flag rows before they hit production.
Integration use cases
Gate CNP fields on HR and onboarding forms
When a user submits a full Romanian CNP, call validate mode and block the save when valid is false, showing expected_check_digit to help correct a single mistype before the employee record is written.
Compute the trailing digit when completing IDs
From a twelve-digit body, call compute mode and store with_check or formatted so every new CNP string carries the correct trailing digit before print, export, or filing generation.
Technical questions
Are spaces and hyphens allowed?
Yes. Common separators are stripped before parsing. Letters, other punctuation, and broken hyphen patterns are rejected with invalid_input.
What does the Romanian CNP check digit calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.