Hourly to annual salary
At 25 an hour for 40 hours a week, you earn 52,000 a year before tax: the wage times your weekly hours times 52 weeks. Compare an hourly offer with rent, loans or a salaried job. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Hourly rate
- 25
- Weekly hours
- 40
- Weeks per year
- 52
- Weekly pay
- 1,000
- Annual salary
- 52,000
An hourly wage is the figure printed on a job posting; an annual salary is the figure used for rent, taxes, and competing offers. Candidates, recruiters, and household budget apps search hourly to annual salary when they need that conversion without opening a spreadsheet. This calculator multiplies a non-negative hourly rate by weekly working hours and by fifty-two weeks — the payroll year used by United States and United Kingdom tables — and returns the gross annual salary in the same currency. Weekly hours cannot exceed one hundred sixty-eight, the hours in seven twenty-four-hour days, so a typo cannot invent more time than a week contains.
What hourly-to-annual conversion means and why fifty-two weeks is the year
Converting hourly pay to annual salary is the search people run the moment an offer is quoted per hour and every other number in their life is quoted per year. Rent, student-loan estimates, health-insurance brackets, and salaried competitors all live on a yearly axis, so the candidate has to inflate a wage into a salary before they can compare anything. The identity is a product of three quantities and nothing else.
Hourly rate times hours worked in a typical week is weekly pay. Weekly pay times fifty-two, the number of weeks in the calendar year that payroll tables use, is annual salary. This calculator always uses fifty-two weeks: it does not ask how many weeks you take unpaid, it does not look at a calendar for a fifty-three-week year, and it does not invent overtime premiums on hours above forty.
Those extras belong in a payroll engine, not in a converter whose job is a reproducible gross figure. Zero hours or a zero wage are allowed and yield a zero annual salary, matching a paused contract or unpaid leave. Weekly hours cannot exceed one hundred sixty-eight because a week is seven twenty-four-hour days and no schedule can consume more clock time than that.
Where an hourly to annual salary converter earns its keep
Careers pages and applicant-tracking add-ons rank for hourly to annual salary because visitors think in yearly rent and yearly student-loan payments, not in the wage printed on a shift posting. Staffing firms and shift marketplaces live on hourly rates; multiplying wage by weekly hours times fifty-two gives the same annual number a recruiter can drop into an offer letter without remembering the conversion or confusing it with a two-thousand-and-eighty-hour rule of thumb that only holds for a forty-hour week.
Educators teaching the difference between a forty-hour week and a thirty-seven-and-a-half-hour week can seed classroom examples that fail loudly when someone types two hundred hours instead of silently printing a six-figure fantasy. Failed validation does not consume balance. Keep the wage and hours non-negative, keep weekly hours at or below one hundred sixty-eight, pin the rounded money fields in tests, and you get a reproducible annual salary for widgets, course modules, and edge workers without standing up a payroll engine of your own.
What you can do with it
Hourly offer to yearly comparison
Turn a wage quoted per hour and a typical weekly schedule into the gross annual salary used to compare against salaried jobs.
Staffing and shift marketplaces
Convert a contractor hourly rate and booked weekly hours into the yearly figure a recruiter can print on an offer letter.
FAQ
How do I convert an hourly wage to an annual salary?
Gross annual salary is hourly rate times hours per week times fifty-two.
Why does the calculator reject weekly hours above 168?
A week contains seven twenty-four-hour days, which is one hundred sixty-eight hours.
Does the converter use 2080 hours a year?
Only when the week is exactly forty hours, because forty times fifty-two is two thousand eighty. Part-time and 37.5-hour weeks use the same identity with their own weekly hours; the calculator never hard-codes 2080.
Is this net take-home pay?
No. The result is gross annual salary in the same currency as the wage. Tax, retirement, and insurance withholding are out of scope so the figure stays a deterministic product of rate, hours, and fifty-two weeks.
Does it add overtime pay for hours above 40 a week?
No. Every hour you enter is multiplied by the same hourly rate, with no overtime premium added, so the result is a plain gross figure you can check by hand.
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/hourly-to-annual-salary \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"hourly_rate":25,"weekly_hours":40}'const res = await fetch("https://api.kit.forhosting.com/fin/hourly-to-annual-salary", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"hourly_rate": 25,
"weekly_hours": 40
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/hourly-to-annual-salary",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"hourly_rate": 25,
"weekly_hours": 40
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/hourly-to-annual-salary", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"hourly_rate":25,"weekly_hours":40}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"hourly_rate":25,"weekly_hours":40}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/hourly-to-annual-salary", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"hourly_rate": 25,
"weekly_hours": 40
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.hourly_to_annual_salary",
"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_abs_value | 1000000000000000 |
max_hours_per_week | 168 |
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
Negative wages or hours fail with invalid_input instead of a nonsense negative salary.
What hourly-to-annual conversion means and why fifty-two weeks is the year
Negative hours or a negative wage cannot describe a schedule, so they fail with invalid_input instead of printing a negative salary a form might display as a debt. The result is gross annual pay in the same currency unit as the wage: no tax, retirement, or insurance is withheld, and no currency conversion is applied.
Input contract, the one-hundred-sixty-eight-hour cap, and the response shape
One hundred sixty-eight is seven times twenty-four: the entire clock of a week. A value of one hundred sixty-nine or two hundred is treated as a data error, not as heroic overtime, because a converter that accepts more hours than a week contains will invent an annual salary no human could earn. Example: twenty-five per hour at forty hours per week yields an annual salary of fifty-two thousand because twenty-five times forty times fifty-two is fifty-two thousand. Example: eighteen point seventy-five per hour at thirty-seven point five hours per week yields thirty-six thousand five hundred sixty-two and fifty cents. POST a JSON body with two required fields. hourly_rate is the gross wage per hour in a single currency unit, a finite number that is not negative, with aliases hourly, rate, wage, hourly_wage, and pay_rate. weekly_hours is the hours worked in a typical week, a finite number that is not negative and not greater than one hundred sixty-eight, with aliases hours, hours_per_week, hrs, and hours_week. Each numeric field may arrive as a JSON number or as a numeric string. Missing fields, empty strings, non-finite values, a negative wage, negative hours, or weekly hours above one hundred sixty-eight fail with invalid_input naming the field and are not billed. On success the body echoes hourly_rate and weekly_hours rounded to two decimals, reports weeks_per_year as fifty-two, returns weekly_pay as the product of wage and hours, returns annual_salary as that weekly pay times fifty-two, and includes a formula string restating the identity. Pair the gross figure with your own withholding table if you need net take-home; this endpoint computes annual gross only.
Where an hourly to annual salary converter earns its keep
Household budget apps can store the returned annual_salary as a yearly inflow and then divide it by twelve or twenty-six themselves, knowing the source of truth was a fifty-two-week product rather than a guessed month.
Integration use cases
Household budget from a wage
Store annual_salary as a yearly inflow from an hourly job so rent and savings plans sit on the same yearly axis as salaried income.
Technical questions
What does the hourly to annual salary converter cost?
The browser tool is free. API requests use prepaid balance at $0.002 per successful call; invalid input is not billed.