CUSIP check digit calculator
Enter the eight-character body of a CUSIP and get its ninth character: 03783310 gets check digit 0 and becomes 037833100. Paste a full nine-character code instead to confirm the last digit before a trade is booked. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Cusip
- 03783310
- Calculation mode
- Compute
- Input
- 03783310
- Check digit
- 0
- Cusip
- 037833100
CUSIP identifiers label North American equities, bonds, and other securities so clearing systems, order tickets, and portfolio files agree on the same nine-character code. The first eight characters identify the issuer and issue; the ninth is a check digit computed from the body so that a single mistype or transposition often fails validation before a trade is booked against the wrong instrument. This capability implements that standard check-digit algorithm: it maps digits and letters to values, doubles alternate positions, sums decimal digits, and returns the digit that makes the total a multiple of ten.
How the CUSIP check digit is computed
A CUSIP is nine characters long under the familiar ANSI X9.6 style layout: six characters for the issuer, two for the issue, and one trailing check digit. Walking the eight body characters from left to right, values in the second, fourth, sixth, and eighth positions are doubled. Each resulting number is reduced by summing its decimal digits—for example fourteen becomes five—so that large letter values do not dominate the total.
Those digit sums are added together. The check digit is ten minus the total modulo ten, and that result itself modulo ten, which yields a single digit from zero through nine. Appending that digit produces a full nine-character CUSIP whose weighted digit sum is congruent to zero modulo ten.
Compared with retail barcode check digits such as EAN-13 or with Luhn on payment cards, CUSIP is alphanumeric and fixed length, which is why it belongs among encoding utilities for security identifiers rather than among product-barcode validators.
Where CUSIP check digits fit real workflows
Broker-dealers and buy-side operations teams ingest end-of-day position and trade files where a single transposed character can book risk against the wrong bond or equity. Validating every CUSIP on import and quarantining rows where valid is false prevents silent master-data pollution. Transfer-agent and corporate-actions desks recompute check digits when issuer and issue codes are assembled from separate feeds, using compute mode so the stored nine-character code matches industry convention.
Integration tests and data-quality jobs recompute the expected check digit for every row in a CSV export and flag rows where the stored full CUSIP no longer matches, which catches both human edits and off-by-one bugs in generators. Do not treat a passing CUSIP check as proof that the security exists, is liquid, or is authorized for trading—it only proves the nine-character string is well formed under this algorithm, the same honesty bar you apply to any checksum.
What you can do with it
Complete an eight-character CUSIP body
When a feed or spreadsheet provides only the eight-character issuer-plus-issue body, call compute mode and store the returned full cusip so every downstream system receives a standard nine-character identifier.
Audit security-master exports
Batch-validate every CUSIP column in a portfolio, custody, or corporate-actions export and quarantine rows whose trailing check digit no longer matches the recomputed expected value.
FAQ
What is a CUSIP check digit?
It is the ninth character of a CUSIP, a single digit 0–9 computed from the eight-character body so that common typing errors often fail a modular checksum before the wrong security is used.
Which characters are allowed?
Digits 0–9, letters A–Z (case-insensitive), and optionally * @ #. Spaces and hyphens are stripped.
Is the CUSIP check digit tool free?
The browser tool is free and runs locally.
How is the CUSIP check digit calculated?
Each of the eight body characters becomes a number, with digits kept as they are and letters A to Z worth ten and up. Values in even positions are doubled, the digits of each result are added, and the check digit is what brings the total to a multiple of ten.
Does a valid CUSIP prove that the security exists?
No. A matching check digit only shows that the nine characters are well formed under the CUSIP rule. The tool does not look anything up, so it cannot confirm that the security exists, trades or is authorized.
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/cusip \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"cusip":"03783310"}'const res = await fetch("https://api.kit.forhosting.com/enc/cusip", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"cusip": "03783310"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/enc/cusip",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"cusip": "03783310"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/enc/cusip", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"cusip":"03783310"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"cusip":"03783310"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/enc/cusip", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"cusip": "03783310"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "enc.cusip",
"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
Use compute mode when you hold only the eight-character body and need the trailing digit, or validate mode when you receive a full nine-character CUSIP and need a boolean plus the expected digit for error messages. Non-CUSIP characters and wrong lengths fail with a clear invalid_input error instead of silent corruption. Run it free in the browser or call the KIT API at the published price; both paths use the same pure arithmetic with no network lookup of security master data.
How the CUSIP check digit is computed
Each body character maps to a number: digits zero through nine stay as themselves, letters A through Z become ten through thirty-five, and the special symbols asterisk, at-sign, and hash become thirty-six, thirty-seven, and thirty-eight when they appear. This tool applies that standard walk exactly; it does not invent a house variant and it always names the algorithm as cusip in the JSON so downstream logs can record which scheme protected the field.
Compute mode versus validate mode
Send a cusip field that contains only allowed characters after optional spaces and hyphens are stripped. Mode validate expects exactly nine characters, with the ninth a digit zero through nine. Empty strings, missing cusip, wrong length for the chosen mode, non-digit ninth characters under validate, and invalid mode values fail before any weighted sum runs and are not billed. Letters are accepted case-insensitively and normalized to uppercase in the echoed input so batch jobs can feed mixed-case paste from spreadsheets. Mode compute is the default and requires exactly eight characters: the engine maps and weights the body, returns check_digit as a one-character string, and returns cusip as the full nine-character identifier so you can store or print a single string. The response reports valid true when the stored trailing digit matches the recomputed expected_check_digit, and always includes body without the last character so user interfaces can highlight what was typed versus what the algorithm expects. 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 protect bulk security-master imports, onboarding forms, and order-entry screens without negotiating a custom tier. Prefer compute when you mint or complete a body from a data vendor that omits the check digit; prefer validate when a user, a partner file, or a scanner submits a full CUSIP and you need a boolean gate before looking up the instrument.
Where CUSIP check digits fit real workflows
Portfolio and performance systems that accept manual security entry can show expected_check_digit next to a failed field so operations staff correct one mistype instead of opening a research ticket. Product teams building order tickets or watchlists can gate submission on validate mode before calling a market-data or trading API that would otherwise reject the symbol with a less clear error.
Integration use cases
Validate typed or imported CUSIPs at entry
When a user or partner file submits a full nine-character CUSIP, call validate mode and block lookup when valid is false, showing expected_check_digit to help correct a single mistype.
Technical questions
How do I compute a CUSIP check digit with this API?
POST with cusip set to the eight-character body and mode compute (or omit mode). The response includes check_digit and cusip (body plus check digit).
How do I validate a full nine-character CUSIP?
POST with the full nine-character string and mode validate. The response includes valid, check_digit, expected_check_digit, and body without the last digit.