Canadian SIN check digit
The base 04645428 gets check digit 6, giving the full SIN 046454286. Enter eight digits to compute the Luhn digit or nine to validate a complete Social Insurance Number, and catch typos before they reach a tax slip or payroll record. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Number
- 04645428
- Calculation mode
- Compute
- Input
- 04645428
- Check digit
- 6
- With check
- 046454286
A Canadian Social Insurance Number is a nine-digit identifier used for tax filing, employment records, benefits, and many government and payroll systems across Canada. The first eight digits form the base number issued to the individual; the ninth is a check digit produced by the Luhn algorithm so that single-digit mistakes and most swaps are caught before the number is stored or transmitted. This capability implements that official Luhn rule only: compute mode accepts exactly eight base digits and returns the check digit plus the full nine-digit SIN; validate mode accepts a full nine-digit SIN and reports whether the trailing digit matches the recomputed expected value.
How the Canadian SIN Luhn check digit is calculated
Under the Service Canada style rule used for Social Insurance Numbers, a SIN is always nine decimal digits. Positions one through eight form the base identifier; position nine is the check digit. To compute that digit, take the eight-digit base and apply the classic double-add-double Luhn algorithm from the right of that base: double every second digit starting with the rightmost base digit, because once the check digit is appended that rightmost base digit sits in position two from the right of the full nine-digit sequence.
When twice a digit is greater than nine, subtract nine (equivalently sum the tens and units of the product). Add every weighted value; the check digit is ten minus that sum modulo ten, modulo ten again so the complete nine-digit sequence including the check digit has a Luhn total divisible by ten. Validation recomputes the expected digit from the first eight characters and compares it to the ninth digit of the submitted SIN.
The algorithm is deterministic and local: no government registry call, no clock, and no randomness. Compared with generic card Luhn, NPI Luhn, or IMEI Luhn tools, the search intent here is narrow: people who need a Canadian SIN check digit calculator for eight-digit bases or a nine-digit Social Insurance Number checker, not a payment, healthcare, or device tool.
Where Canadian SIN check digits fit real workflows
Payroll and HRIS vendors receive eight-digit internal bases during onboarding sandboxes and must append the official Luhn check digit before a SIN appears on tax slips, direct-deposit forms, or employee records. Tax software and benefits administrators validate nine-digit SINs at entry so a single transposition does not create a phantom employee and a rejected T4 or ROE submission.
ETL jobs that load employee master files walk every SIN column in a CSV or HR feed, call validate mode, and quarantine rows where valid is false—catching both human edits and off-by-one bugs in generators. Do not treat a passing SIN check as proof that the number is currently assigned by Service Canada, that the holder is eligible for a benefit, or that identity has been verified; it only proves the Luhn digit is consistent with the base under the weights used for Canadian Social Insurance Numbers.
Handle real SINs as sensitive personal information: encrypt at rest, limit access, and never log full numbers in application telemetry.
What you can do with it
Audit SIN columns in employee master data
Batch-validate every nine-digit SIN in a payroll, benefits, or tax CSV and quarantine rows whose check digit no longer matches the recomputed expected value.
FAQ
What is a Canadian SIN check digit?
It is the ninth digit of a Canadian Social Insurance Number, computed with the Luhn algorithm over the first eight digits, so typing and scanning errors are usually caught before the number is stored or filed.
Is the Canadian SIN check digit tool free?
The browser tool is free and runs locally.
How is the SIN check digit calculated?
Starting from the rightmost base digit, double every second digit and subtract 9 from any result above 9. Add all the values; the check digit is what brings the total up to a multiple of ten. For 04645428 that digit is 6.
Does a valid SIN mean it was really issued?
No. A matching check digit only shows the number is well formed. The tool does not contact any government registry, so it cannot tell whether a SIN was issued, is still active or belongs to the person who gave it.
Can I enter a SIN with spaces or hyphens?
No. Type digits only, from 0 to 9. Spaces, hyphens and letters are rejected instead of being quietly removed, so an altered number never ends up in your records. You need eight digits to compute and nine to validate.
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/sin-canada \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"number":"04645428"}'const res = await fetch("https://api.kit.forhosting.com/enc/sin-canada", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"number": "04645428"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/sin-canada",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"number": "04645428"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/sin-canada", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"number":"04645428"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"number":"04645428"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/sin-canada", 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": "04645428"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.sin_canada",
"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 input and wrong lengths fail with invalid_input instead of silent stripping, so you never persist a half-cleaned identifier. The same pure arithmetic runs free in the browser and at the published API price, with no network lookup of government registries and no claim that a valid checksum means the SIN is active, issued, or free of fraud.
Input contract, modes, and error behaviour
Send a number field that contains only characters zero through nine. Wrong length is an explicit error that names the mode and the length you sent—eight for compute, nine for validate—so client forms can show “need eight digits” without guessing. Empty strings, missing number, and invalid mode values fail before any Luhn sum runs and are not billed. Failed validation tasks that reject bad shape are not charged; a well-formed nine-digit string that simply has the wrong check digit returns valid false without throwing. Never treat this tool as a way to invent real SINs for living people: use only synthetic or authorized bases in development, and store real SINs under your privacy and security policies. Spaces, hyphens, letters, and decimal points are rejected as non-numeric input with invalid_input so a silently stripped value never reaches storage. Mode validate requires exactly nine digits; the response reports valid true when the trailing digit matches the recomputed expected_check_digit, and always includes payload (the first eight digits), check_digit, expected_check_digit, and length nine. Alias keys such as digits, sin, and code are accepted for the same payload field so integrations that already speak “sin” 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 Canadian SIN check digits fit real workflows
Benefits and employment-insurance teams recompute expected_check_digit when a client reads a number over the phone or pastes it from a PDF, catching mistypes before a claim file is submitted.
Integration use cases
Complete an 8-digit SIN base for payroll fixtures
Call compute mode with the eight-digit base, store with_check, and use the nine-digit SIN in test payroll, tax-slip, or sandbox employee records.
Validate typed or imported SINs at entry
When a form, HRIS file, or partner feed submits nine 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 SIN 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 with_check (the full nine-digit SIN).
How do I validate a full nine-digit SIN?
POST with the nine-digit string and mode validate. The response includes valid, check_digit, expected_check_digit, and payload (digits without the last one).
What happens with wrong length, letters, or hyphens?
Non-numeric input and lengths other than eight (compute) or nine (validate) are rejected with invalid_input. Failed validation tasks are not billed.