Luhn algorithm validator
Find out at once whether a digit string passes the Luhn mod-10 check: 79927398713 does. It catches any single mistyped digit and most swaps of neighbouring digits, without claiming the number exists or belongs to anyone. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
The Luhn algorithm validator checks whether a number string satisfies the widely used mod-10 checksum formula. Supply digits exactly as they appear, including any leading zeros, and receive a simple valid or invalid result. The capability performs checksum validation only: it does not identify an issuer, confirm that an account exists, or contact any outside service. Non-digit input is rejected explicitly instead of being cleaned silently, which makes automation predictable and helps expose formatting mistakes before they enter another system.
What a Luhn result actually tells you
A Luhn checksum is a compact error-detection rule for sequences of decimal digits. Starting at the right, the algorithm keeps the check digit unchanged, doubles every second digit, subtracts nine whenever doubling produces a two-digit value, and adds the resulting values. The number is valid when that total is divisible by ten.
This catches every accidental single-digit change and many common adjacent transpositions, making it useful for detecting routine typing and copying errors. A valid result does not prove that the number was issued, belongs to anyone, is active, or can be used for a transaction. It means only that the supplied string is internally consistent with the Luhn formula.
This distinction matters in user interfaces and data pipelines: label the result as checksum validity, not identity or account verification. The validator preserves the string representation, including leading zeros, and never converts it to a JavaScript number, so long identifiers remain exact rather than losing digits through numeric precision limits.
Preparing input and interpreting errors
Send the value in the <code>number</code> field as a non-empty string containing only the characters zero through nine. Spaces, hyphens, plus signs, decimal points, line breaks, and letters are rejected as invalid input. That strict behavior is intentional.
Silently stripping punctuation can hide an upstream formatting defect, change the meaning of copied data, or make two systems appear to agree when they received different text. If your source presents grouped values, normalize them deliberately in your own workflow before calling this capability, and retain the original value when an audit trail is important. Do not parse the string as an integer first: doing so can remove leading zeros and can round long values.
A value of <code>true</code> means the checksum total is divisible by ten; <code>false</code> means the input was syntactically acceptable but failed the checksum. An input error is different from a false checksum result and should normally trigger correction or review rather than ordinary invalid-number handling.
Using deterministic validation in applications
Use this validator at boundaries where digit strings enter a system: form submission, batch import, migration, test-data generation, or integration testing. For interactive forms, run the browser version after the user finishes entering the value and explain that the check catches likely mistakes without proving that an account exists. For an import, treat non-digit errors as malformed source records and false results as well-formed records whose checksum does not match.
Keeping those cases separate produces better reports and avoids discarding actionable diagnostics. The algorithm is deterministic, uses no network connection, reads no clock, and generates no random values, so identical input always produces identical output. If your domain imposes lengths, prefixes, ownership checks, or live account status, apply those rules separately.
What you can do with it
Catch data-entry mistakes
Check a digit string at form submission and distinguish a checksum mismatch from malformed input containing punctuation or letters.
Validate batch imports
Apply the same deterministic checksum rule to every incoming record before it reaches downstream processing.
FAQ
What does a valid result mean?
It means the digit string satisfies the Luhn mod-10 checksum. It does not confirm issuance, ownership, account status, or transaction eligibility.
Can the input include spaces or hyphens?
No. The input must contain digits only. Normalize formatted values explicitly before submitting them.
Are leading zeros preserved?
Yes. The input is handled as a string and is never converted to a numeric type.
Does the validator require a particular length?
No. It evaluates any non-empty string of digits. Domain-specific length rules must be enforced separately.
How is the Luhn checksum calculated?
Starting from the right, keep the last digit as it is and double every second digit after it. When doubling gives a two-digit number, subtract 9. Add everything up: the string passes when the total is divisible by 10.
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/math/luhn \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"number":"79927398713"}'const res = await fetch("https://api.kit.forhosting.com/math/luhn", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"number": "79927398713"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/math/luhn",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"number": "79927398713"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/math/luhn", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"number":"79927398713"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"number":"79927398713"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/math/luhn", 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": "79927398713"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "math.luhn",
"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
Preparing input and interpreting errors
A successful call always returns an object with one Boolean field named <code>valid</code>.
Using deterministic validation in applications
API calls use the published base price of $0.002; the calculation itself remains a focused checksum operation rather than a broader verification service.
Integration use cases
Build reliable test fixtures
Confirm that known valid and invalid strings behave consistently in integration tests without relying on a network service.
Technical questions
How much does an API call cost?
Each API request uses the published base price of $0.002. The browser experience can run the same deterministic logic locally.