Validate and convert ISBN-10 and ISBN-13 checksums
An ISBN can look convincing while still containing a mistyped digit, and changing between its ten-digit and thirteen-digit forms requires more than adding or removing a prefix.
Run — free
This validator normalizes ordinary spaces and hyphens, identifies the format by length, verifies the complete checksum, and returns canonical ISBN-10 and ISBN-13 values. It rejects malformed identifiers and checksum mismatches instead of producing a plausible but unsafe conversion. The calculation is deterministic, requires no network lookup, and makes a useful validation step for catalogs, imports, publishing systems, and book inventory workflows.
Validate before storing or converting
An ISBN is an identifier with a mathematical check digit, not proof that a particular book exists. This tool first removes ordinary spaces and hyphens, then applies the checksum rule belonging to the detected length. For ISBN-10, the ten positions use descending weights from ten to one, and the final character may be X to represent ten. For ISBN-13, alternating weights of one and three determine the final decimal digit. A mismatch produces an input error, so downstream code never receives a conversion derived from a mistyped source. That behavior is especially valuable during bulk imports, where silently accepting one bad digit can create duplicate catalog records or attach stock to the wrong edition. The returned valid flag confirms that the arithmetic passed, while input_format states which rule was applied. Both output identifiers are unhyphenated canonical strings, making them safe to compare, index, or pass into another system without preserving inconsistent punctuation from the submitted value.
Understand how conversion works
Converting ISBN-10 to ISBN-13 starts with the first nine ISBN-10 digits, discards the old check character, adds the 978 book prefix, and calculates a new ISBN-13 check digit. The reverse operation is available for ISBN-13 values beginning with 978: the prefix and ISBN-13 check digit are removed, then the ISBN-10 checksum is recalculated from the remaining nine digits. The new ISBN-10 check character can be a decimal digit or X. This is why conversion should not be performed by simple text slicing or by copying the existing check digit. ISBN-13 identifiers beginning with 979 are valid members of the ISBN system, but they do not have ISBN-10 equivalents. The tool validates such a number first and then returns a clear input error because it cannot honestly satisfy a request for both formats. It does not invent a ten-digit value, substitute 978, or claim that a lossy transformation is a conversion. That distinction preserves identifier integrity when newer publishing ranges are encountered.
Use the result in reliable workflows
Submit one isbn field as text. Printed forms such as 0-306-40615-2 and 978 0 306 40615 7 are accepted because spaces and hyphens are formatting rather than identifier data. Other letters, punctuation, incorrect lengths, misplaced X characters, non-book EAN prefixes, and failed checksums are rejected. On success, store the returned isbn10 and isbn13 fields rather than rebuilding either value in application code. You can also retain input_format when it matters whether a supplier originally supplied the legacy or modern representation. The capability performs no title, author, edition, ownership, or availability lookup; checksum validity only establishes internal consistency. Pair it with an authoritative catalog source when bibliographic identity must also be confirmed. Because the algorithm is pure arithmetic with no network request, the same input always yields the same output and no external service can change the answer. Browser use is convenient for individual checks, while the API costs $0.002 per request and fits validation at an ingestion boundary before records reach a database, search index, fulfillment process, or reporting pipeline.
What you can do with it
Clean a publisher catalog import
Reject mistyped identifiers and store consistent ISBN-10 and ISBN-13 fields before catalog rows enter the database.
Normalize marketplace listings
Convert seller-supplied ISBN forms into canonical unhyphenated values that can be compared without punctuation differences.
Check a printed book identifier
Paste the ISBN from a cover or copyright page to catch transcription errors and obtain its corresponding format.
FAQ
What does the capability cost?
Each API request costs $0.002. You can also use the browser interface for an individual check.
Does a valid checksum prove that the book exists?
No. It proves only that the identifier is structurally valid and has a matching check digit; no catalog lookup is performed.
Are spaces and hyphens accepted?
Yes. Ordinary spaces and hyphens are removed before validation, and the returned identifiers contain no separators.
Why can a valid 979 ISBN-13 not be converted?
ISBN-10 has an equivalent only for the ISBN-13 range beginning with 978. A 979 identifier has no truthful ten-digit representation.
Can X appear in an ISBN?
Yes, but only as the final ISBN-10 check character, where it represents the checksum value ten. ISBN-13 uses digits only.
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/data/isbn-validate-convert \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"isbn":"0-306-40615-2"}'const res = await fetch("https://api.kit.forhosting.com/data/isbn-validate-convert", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"isbn": "0-306-40615-2"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/data/isbn-validate-convert",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"isbn": "0-306-40615-2"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/data/isbn-validate-convert", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"isbn":"0-306-40615-2"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"isbn":"0-306-40615-2"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/data/isbn-validate-convert", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"isbn": "0-306-40615-2"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "data.isbn_validate_convert",
"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.
Limits
max_mb | 25 |
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. |