True shooting % calculator
25 points on 18 field-goal attempts and 8 foul-shot attempts is a true shooting percentage of 58.0855: one efficiency rate that counts twos, threes and foul shots together. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Points
- 25
- Fga
- 18
- Fta
- 8
- Ts percent
- 58.0855018587
- Ts
- 0.5808550186
- True shooting attempts
- 21.52
True shooting percentage, abbreviated TS%, is the basketball scoring-efficiency rate that folds field goals and free throws into one number so a night of and-ones is not scored the same as a night of empty possessions at the same raw field-goal percentage. This calculator accepts points scored, field-goal attempts, and free-throw attempts, then returns the percentage using the standard identity points divided by two times the quantity field-goal attempts plus 0.44 times free-throw attempts. Negative attempts are rejected because a box score cannot go below zero. Zero combined shooting attempts are rejected because the rate is undefined when nobody attempted a field goal or a free throw.
What true shooting percentage measures and why FG% is not enough
True shooting percentage, often written TS% on Basketball-Reference, NBA.com, and modern box scores, answers a question that raw field-goal percentage cannot: how efficient was this shooter once free throws and the extra value of three-pointers, captured through total points, are folded into one rate?
A player who scores twenty-five points on eighteen field-goal attempts and eight free-throw attempts used a mix of twos, threes, and trips to the line; a teammate with the same field-goal percentage but zero free throws is not equally efficient, because the first night also converted possessions at the stripe. The standard identity, used by Basketball-Reference and the league's public stats, is TS% equals points divided by two times the quantity field-goal attempts plus 0.44 times free-throw attempts, then scaled to a percentage.
The 0.44 coefficient estimates possessions consumed by free throws, because not every free-throw attempt is a two-shot foul: and-ones, technicals, and three-shot fouls change the trip length. This calculator implements that identity exactly. It does not estimate shot quality from tracking cameras, does not scrape a league feed, and does not compute effective field-goal percentage, which ignores the line entirely and instead weights made threes inside the make rate.
You already have points, field-goal attempts, and free-throw attempts from the same split; you get a deterministic percentage you can recompute by hand. Treat the number as a transparent scoring-efficiency figure, not as a player ranking, defensive context, or expected-true-shooting model from spatial tracking.
Practical tips, limits, and when to use this calculator
Copy points, field-goal attempts, and free-throw attempts from the same split: a player game, a team half, a season, or a play-type slice all work as long as the three numbers describe the same sample. Do not mix a player's points with a team's attempts. Count every made two, three, and free throw in the points total; do not substitute field goals made for points, because TS% is a scoring-efficiency rate, not a make rate.
Effective field-goal percentage is the sibling that ignores free throws and weights threes inside the make rate; use that tool when you have field goals made, three-pointers made, and field-goal attempts and you do not have points or free throws. A perfect night of only threes can push TS% above one hundred percent: one-for-one from three with zero free throws is one hundred fifty percent true shooting, which is correct, not a bug.
Stay inside the published limits of one million on each input, which covers a career or a league-wide rollup without inviting unbounded numbers. Prefer this capability when you already have the three counting stats and only need the standard 0.44 identity. Round-trip checks are easy: twenty-five points, eighteen FGA, and eight FTA should return the same percentage every time.
What you can do with it
Scouting and box-score conversion
Analysts paste points, FGA, and FTA from a game or stretch and publish TS% next to raw FG% without a spreadsheet formula drifting between files.
Classroom efficiency drills
Coaches and teachers generate answer keys that apply PTS / (2 × (FGA + 0.44 × FTA)) so students see why two identical FG% nights are not equally efficient at the line.
FAQ
How is true shooting percentage calculated?
TS% = PTS / (2 × (FGA + 0.44 × FTA)) × 100. Points divided by two times true shooting attempts, then scaled to a percentage. True shooting attempts equal field-goal attempts plus 0.44 times free-throw attempts.
Why is the free-throw coefficient 0.44?
Not every free-throw attempt consumes a full possession. And-ones, technicals, and three-shot fouls change trip length. Basketball-Reference and NBA public stats use 0.44 as the standard estimate of possessions used at the line.
What happens if field-goal attempts or free-throw attempts are negative?
A box score cannot go below zero, so a negative fga or fta is rejected rather than producing a nonsense percentage. Negative points fail the same way.
How is TS% different from effective field goal percentage?
eFG% weights made threes inside the make rate and ignores free throws. TS% uses total points, so it includes the line and the extra value of threes through scoring. They answer different questions and take different inputs.
Is the true shooting percentage calculator free?
The browser tool is free and runs locally.
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/sports/ts \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"points":25,"fga":18,"fta":8}'const res = await fetch("https://api.kit.forhosting.com/sports/ts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"points": 25,
"fga": 18,
"fta": 8
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/sports/ts",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"points": 25,
"fga": 18,
"fta": 8
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/sports/ts", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"points":25,"fga":18,"fta":8}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"points":25,"fga":18,"fta":8}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/sports/ts", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"points": 25,
"fga": 18,
"fta": 8
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "sports.ts",
"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_points | 1000000 |
max_fga | 1000000 |
max_fta | 1000000 |
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
How to call the API, which fields it needs, and how errors are raised
Negative points fail the same way, naming the field that went below zero. Missing fields, empty strings, and non-finite values fail naming the field. A classic check is twenty-five points on eighteen field-goal attempts and eight free throws: true shooting attempts equal 21.52, and TS% equals twenty-five divided by 43.04 times one hundred. Wire the free browser form for scouting and homework, then call the identical contract from scripts when you need bulk box-score conversion. Send a JSON body with three required numeric fields. The field points is points scored, a non-negative finite number from zero through one million, with aliases pts and points_scored. The field fga is field-goal attempts, a non-negative finite number in the same range, with aliases field_goal_attempts and fg_attempts. The field fta is free-throw attempts, a non-negative finite number with aliases free_throw_attempts and ft_attempts. When either attempt count is negative the task fails with invalid_input, because a box score cannot go below zero and a negative denominator term would not describe a real shooting night. When both fga and fta are zero the task also fails with invalid_input, because TS% is a ratio and the denominator two times true shooting attempts would be zero. On success the body returns ts_percent as the primary percentage, ts as the same rate on a decimal scale, true_shooting_attempts as FGA plus 0.44 times FTA, the echoed inputs, the formula string, method standard_ts, a short message, and an ordered steps array you can show next to the answer. Pricing for successful API calls is the published base of $0.002 per item; validation failures do not consume prepaid balance.
Practical tips, limits, and when to use this calculator
Failed tasks that return invalid_input do not consume prepaid balance, which keeps exploratory scripts cheap when you deliberately send a negative attempt count to test client validation. This page targets people searching for a true shooting percentage calculator, TS% calculator, or true shooting from points FGA FTA; it is not an eFG tool, not a points-per-possession model, and not a tracking expected-efficiency estimator. API pricing remains $0.002 per successful request with unit item.
Integration use cases
Season logs and app shooting columns
Stat apps store the three counts per game, then call this tool once to fill a TS% column that matches the free browser widget byte for byte.