GRP calculator
40% reach at an average frequency of 3 delivers 120 gross rating points. Multiply reach by frequency to compare the advertising weight of weeks, channels or media plans on one scale, straight from a post-buy or a planning grid. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Reach
- 40
- Frequency
- 3
- Grp
- 120
Gross rating points, or GRP, are the standard weight of linear television, radio, out-of-home, and many still-used campaign scorecards: they compress how widely a message was seen and how often those people were exposed into a single number media planners can compare across weeks and vehicles. This GRP calculator multiplies reach percentage by average frequency of exposure, the identity every media-math textbook prints as GRP equals reach times frequency. Reach is the share of the target universe exposed at least once, expressed as a percent that cannot exceed one hundred. Frequency is the average number of times those reached people saw or heard the creative.
What gross rating points measure and how the product is formed
Gross rating points measure the total advertising weight delivered against a defined target universe. One GRP is equivalent to reaching one percent of that universe once. The identity this calculator implements is the product every media planner learns first: GRP equals reach percent times average frequency of exposure.
Reach is the unduplicated share of the target exposed at least once, expressed as a percentage from zero to one hundred. Frequency is the average number of times those reached people were exposed to the creative during the flight. Forty percent reach at an average of three exposures is one hundred twenty GRPs, because forty times three is one hundred twenty.
The same one hundred twenty GRPs can be assembled many ways: twenty percent reach at six exposures, sixty percent reach at two exposures, or one hundred percent reach at one point two exposures. That is why GRP is a weight, not a unique-audience claim: two plans with identical GRPs can still differ on how concentrated or how broad the delivery was. This task does not ingest a raw ad-server log, does not apply duplication across vehicles, and does not convert impressions into reach.
It prices and returns the textbook product on two numbers you already have from a post-buy, a planning grid, or a weekly recap. Frequency of zero is a legitimate outcome and returns grp of zero rather than an error. Reach of one hundred is also legitimate: the entire universe was reached at least once.
What is not legitimate is a reach above one hundred percent, because a universe share cannot exceed the universe, and a negative reach or frequency, because neither quantity can be negative in media math.
Where a GRP calculator earns its keep
Media planners, buyers, and client-side brand teams use a GRP calculator when a campaign, a week, or a vehicle is accused of under-delivering weight: they already have reach and frequency from a post-buy or a planning grid and need the same product their buying system would print, without waiting on a proprietary export. Agencies re-run the two numbers per station, daypart, and demographic so a weekly deck can compare GRPs across variants with one shared rounding rule.
GRP multiplies reach percent by average frequency against the defined universe and says nothing about cost, clicks, or on-site engagement. Out-of-home and radio teams use the same identity on audience-currency reach; this task does not choose the currency for you — it computes the product on the two numbers you supply. Failed validation does not consume balance.
Keep reach at or below one hundred percent, keep frequency non-negative, pin the rounded product in tests, and you get reproducible gross rating points for dashboards, LMS plugins, and edge workers without standing up a media-math engine of your own.
What you can do with it
Weekly campaign scorecards
Turn a week's reported reach percent and average frequency into the GRP you can put next to each vehicle in a paid-media recap.
Plan versus post-buy checks
Recompute grp per station, daypart, or demographic from two planning-grid numbers so every variant shares the same product and rounding.
FAQ
How are gross rating points calculated?
Send finite numbers reach (a percent from 0 to 100) and frequency (average exposures among those reached).
What happens if reach exceeds 100 percent?
Gross rating points use a percentage of the target universe, so a share above 100 percent is rejected and is not billed.
Is reach a percent or a 0–1 fraction?
A percent on a 0–100 scale. Forty percent reach is 40, not 0.4. Sending 0.4 is treated as four tenths of one percent.
Can average frequency be zero?
Yes. A zero frequency is a legitimate empty flight and returns grp of zero.
Do two plans with the same GRP reach the same people?
Not necessarily. GRP measures weight, not unique audience. The same 120 points can be 20% reach at 6 exposures, 60% reach at 2, or 100% reach at 1.2, which are very different plans.
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/fin/grp \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"reach":40,"frequency":3}'const res = await fetch("https://api.kit.forhosting.com/fin/grp", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"reach": 40,
"frequency": 3
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/grp",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"reach": 40,
"frequency": 3
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/grp", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"reach":40,"frequency":3}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"reach":40,"frequency":3}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/grp", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"reach": 40,
"frequency": 3
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.grp",
"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
Input contract, response shape, and error behaviour
On success the body echoes reach and frequency, then reports grp as the product rounded half-up to six decimal places, and a formula string restating the identity. Example: forty percent reach and frequency three yield grp one hundred twenty. Reach is a percent on a zero-to-one-hundred scale, not a zero-to-one fraction: sending 0.4 is treated as four tenths of one percent, not forty percent. POST a JSON body with two required finite numbers. reach is the percent of the target universe exposed at least once; aliases reach_percent, reach_pct, and reach_percentage map to the same field so a warehouse column can keep its name. frequency is the average number of exposures among those reached people; aliases avg_frequency and average_frequency are accepted. Each field may arrive as a JSON number or as a numeric string. Missing fields, empty strings, and non-finite values fail with invalid_input naming the field. If reach is negative the request fails. If frequency is negative the request fails. Those failures are not billed. Pair the JSON with your own date grain if you need a weekly series; this task computes one window at a time and does not emit charts or vehicle mixes.
Where a GRP calculator earns its keep
Finance partners who allocate spend against delivered weight drop reach and frequency from the warehouse and pin grp in a model that must not call a media-agency API. This is a different search and a different job from computing click-through rate, cost per mille, or bounce rate: CTR divides clicks by impressions, CPM divides spend by a thousand impressions, and bounce rate divides single-page sessions by sessions.
Integration use cases
Spend-against-weight models
Pin gross rating points in a spend-allocation sheet without calling a proprietary media API for a product you already have the inputs for.
Technical questions
What does the GRP calculator cost?
The browser tool is free. API requests use prepaid KIT balance at $0.002 per successful call; invalid input is not billed.