GPA calculator
List each course with its letter grade and credits: an A and a B worth 3 credits each give 21 quality points over 6 credits, a GPA of 3.5. The average is weighted by credits, not a plain mean of grades. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Computes a grade point average on the standard 4.0 scale from a list of courses, each with a letter grade and credit hours, returning the weighted GPA, total credits, quality points, and course count.
The 4.0 grade table and credit weighting
The calculator converts each letter grade to quality points on the standard 4.0 scale using a fixed table: A is 4.0, A- is 3.7, B+ is 3.3, B is 3.0, B- is 2.7, C+ is 2.3, C is 2.0, C- is 1.7, D+ is 1.3, D is 1.0, and F is 0.
Every entry in the courses array carries a grade and a credits value; the engine multiplies each grade's points by its credits to get weighted quality points, sums them, sums the credits, and divides to produce a credit-weighted GPA — not a naive average of grade points.
Rounding, decimals and fractional credits
The helper computes sign * Math.floor(abs(x) * 10^decimals + 0.5) / 10^decimals, so a value exactly at the midpoint always rounds away from zero. The decimals parameter controls precision, defaults to 2, and must be an integer from 0 to 3 — pass 0 for a whole-number GPA or 3 for finer granularity when comparing close records.
What the calculator accepts and rejects
Validation runs before any arithmetic. courses must be an array holding between 1 and 50 items, so an empty list or an oversized batch both fail fast and cannot hang the tab. Each entry must be an object; a grade outside the eleven-value table throws 'grade inválido' (there is no rounding of unknown letters to the nearest bucket), and a credits value that is missing, non-numeric, non-finite, or zero-or-negative throws 'credits inválido'. decimals outside 0-3 throws 'decimals fuera de rango', and a non-object top-level input is rejected outright.
What you can do with it
Student dashboards
Recompute a term or cumulative GPA the instant a grade or credit value changes.
Scholarship checks
Verify whether a weighted GPA clears a threshold before approving an application.
FAQ
What grade scale is used?
A fixed 4.0 table from A (4.0) down to F (0), including plus/minus steps.
Is the GPA credit-weighted?
Yes. Each grade's points are multiplied by its credits, summed, then divided by total credits.
Can courses have fractional credits?
Yes. credits can be any positive finite number, such as 1.5 for a half-credit course.
What are quality points?
They are each course's grade points multiplied by its credits, added together. Dividing that total by the total credits gives the GPA, which is why a heavy course moves the average more than a light one.
What happens if I type a grade that is not on the scale?
It is rejected rather than rounded to the nearest letter. Only the eleven grades from A to F on the 4.0 table are accepted, in capitals or lowercase, so a- and A- count the same.
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/dev/gpa-calculator \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"courses":[{"grade":"A","credits":3}]}'const res = await fetch("https://api.kit.forhosting.com/dev/gpa-calculator", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"courses": [
{
"grade": "A",
"credits": 3
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev/gpa-calculator",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"courses": [
{
"grade": "A",
"credits": 3
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev/gpa-calculator", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"courses":[{"grade":"A","credits":3}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"courses":[{"grade":"A","credits":3}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev/gpa-calculator", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"courses": [
{
"grade": "A",
"credits": 3
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev.gpa_calculator",
"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
The 4.0 grade table and credit weighting
The response returns gpa, total_credits (the sum of all credits), quality_points (the summed grade-point total), and courses_count. With an A over 3 credits and a B over 3 credits, quality_points is 21, total_credits is 6, and gpa is 3.5.
Rounding, decimals and fractional credits
Grades are read case-insensitively because the input is upper-cased before lookup, so 'a-' and 'A-' are equivalent. credits may be any positive finite number, including fractional weights like 1.5, letting you model labs and half-credit seminars. total_credits is returned as the exact sum of credits, while gpa and quality_points are both rounded to the chosen decimals.
Integration use cases
Registrar automation
Batch grade rosters through the API to post official GPAs deterministically.
Technical questions
How many courses can I submit?
Between 1 and 50 per request; outside that range returns invalid_input.
Is it free?
Yes in the browser widget; the API runs the same logic from $0.002 per call.