Darts Checkout Calculator
This darts checkout calculator turns a remaining score into a legal finish for standard 501-style play.
Run — free
Enter an integer from 2 through 170 and receive a deterministic combination using no more than three darts, with the last dart always landing in a double or the double bull. The result includes familiar board notation and a detailed breakdown of every suggested hit. If no legal three-dart checkout exists, the calculator returns a clear error instead of presenting an impossible route.
Enter the score that remains before your visit
Use the score shown after the previous visit, before throwing any of the next three darts. The calculator accepts whole-number remaining scores from 2 to 170, the largest standard three-dart checkout. It then looks for a route that uses one, two, or three darts and finishes on a legal double. For example, a remaining score of 40 can be completed immediately with D20, while a larger total may require triples before the final double. The notation in the response follows common darts shorthand: S means a single segment, D means a double, T means a triple, SB means the single bull worth 25, and DB means the double bull worth 50. The detailed dart objects also state the segment, multiplier, and scored points, making the result useful in an interface even when a reader does not know the shorthand. Enter only the current remainder, not the original starting score of 501 and not the sum already scored in the leg.
Understand what makes a checkout valid
Standard 501 play uses the double-out rule: the dart that reduces the score to exactly zero must be a double. A double bull is valid because it is the double ring of the bull and scores 50. Singles, triples, and other doubles may appear earlier in the route, but the last listed dart is always a double. The search uses only real dartboard targets: singles, doubles, and triples from 1 through 20, plus single and double bull. It never invents a segment such as T21 or treats an inner single number as a finishing double. The algorithm checks shorter finishes before longer ones, so a one-dart checkout is returned when available and a two-dart route is preferred over a three-dart route. Within the same length it follows a fixed ordering that favors high triples, then bull and doubles, which keeps repeated calls stable. A suggested route is valid mathematically; players can still choose a different route that better suits their favorite doubles or match strategy.
Handle bogey numbers and use the result responsibly
Not every score in the accepted range can be finished in three darts. Familiar bogey numbers such as 169, 168, 166, 165, 163, 162, and 159 cannot be made with three legal hits while also ending on a double. A score of 1 is not a checkout either, because no positive double scores one point. When the requested score has no route, the capability returns an invalid-input error that names the score and explains the three-dart double-out restriction. This is preferable to silently suggesting a setup shot, because a setup visit does not complete the leg and answers a different question. You can use the successful response to power a practice prompt, a scorer display, a coaching worksheet, or automated commentary. The combination array is convenient for compact display, while the darts array supports richer layouts and validation. The calculation is pure and local: it does not use player profiles, network services, randomness, or live match data, so the same input always produces the same suggested checkout.
What you can do with it
Plan a league checkout
Turn the score shown on a match scorer into a legal route before beginning the next three-dart visit.
Build checkout practice drills
Generate stable targets and board notation for repeatable double-out training sessions.
Add hints to a darts scorer
Display a compact combination or a detailed per-dart breakdown inside a scoring application.
FAQ
What does one request cost?
The API price is $0.002 per request. The same deterministic calculation can run free in your browser on this page.
Does the final dart always land on a double?
Yes. Every successful result ends with D1 through D20 or DB, the double bull.
Why does a score below 170 sometimes return an error?
Some totals are bogey numbers that cannot be scored with at most three legal darts while finishing on a double.
What do T20, D20, SB, and DB mean?
They mean triple 20, double 20, single bull worth 25, and double bull worth 50.
Will this always return the route a professional player would choose?
Not necessarily. It returns a valid, stable, short route; personal preferences and tactical setup choices can make another valid route more comfortable.
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/game/dart-score-checkout \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"score":170}'const res = await fetch("https://api.kit.forhosting.com/game/dart-score-checkout", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"score": 170
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/game/dart-score-checkout",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"score": 170
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/game/dart-score-checkout", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"score":170}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"score":170}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/game/dart-score-checkout", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"score": 170
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "game.dart_score_checkout",
"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. |