The Indian payroll maths that is easy to get subtly wrong

A zero-dependency, MIT-licensed JavaScript package for FY 2026-27 statutory salary calculations — new-regime income tax, gratuity, HRA exemption and state-wise professional tax. Every function is pure, every rule is tested, and the slab data ships as plain JSON you can read.

MIT Zero dependencies 17 tests FY 2026-27

npm install india-payroll-rules   # or copy src/index.js — it is one file

const { incomeTax, gratuity, hraExemption, professionalTax } = require("india-payroll-rules");
Everything on this page is computed in your browser by the package itself. docs/rules.browser.js is generated from src/index.js and data/*.json by scripts/build-docs.js, so these numbers cannot drift from the published library.

Playground

Change any input; the figures update from the real implementation.

inHandSalary()

Take-home pay from CTC

incomeTax()

New-regime income tax, with Section 87A marginal relief

gratuity()

Gratuity under the Payment of Gratuity Act

hraExemption()

HRA exemption — Section 10(13A), least of three limbs

professionalTax()

State professional tax, capped by Article 276

Four rules that are easy to get wrong

These are the reasons this package exists. Each figure below is computed live, so you can check the claim rather than take it.

1. Section 87A has marginal relief just past ₹12 lakh

Below ₹12,00,000 of taxable income the rebate wipes the tax out entirely. Cross that line by ₹1 and the slab tax is not ₹0 — but it is also not the full slab figure. Relief caps the tax at the amount by which income exceeds the limit, so a small raise can never cost more than it pays.

2. Gratuity rounds a part-year up only when it exceeds six months

Exactly six months does not round up; six months and a day does. And an employer outside the Payment of Gratuity Act divides by 30, not 26 — roughly 13% less for the same service.

3. Fixed-term employees qualify for gratuity after one year, not five

The 2025 Labour Codes carry forward the rule that a fixed-term employee earns gratuity on completing one year of service. Applying the usual five-year minimum to them understates the liability.

4. Professional tax is capped at ₹2,500 a year — which is why the slabs look odd

Article 276 of the Constitution caps the total any state may levy on a profession, trade or employment at ₹2,500 a year. States notify slabs that deliberately land just under that ceiling, which is why the top band in Tamil Nadu, Madhya Pradesh, Kerala and Bihar is an oddly-specific ₹208 a month — twelve of those is ₹2,496, four rupees of headroom.

With the slabs as they stand today the cap is never actually binding, so monthly × 12 happens to give the right answer everywhere. The library applies min(2500, monthly × 12) anyway, so that a future state revision cannot produce a figure the Constitution does not allow.

API

incomeTax(taxableIncome)        // income AFTER the ₹75,000 standard deduction
  → number — tax payable, rounded, incl. 87A relief + surcharge + cess

slabTax(taxableIncome)          // slabs only, before rebate/surcharge/cess
surchargeRate(taxableIncome)    // 0 | 0.10 | 0.15 | 0.25

inHandSalary({ ctc, basicPercent = 0.5, pf = "full", professionalTax = 2400 })
  → { ctc, basic, gross, employerPf, employeePf, professionalTax,
      taxableIncome, incomeTax, annualNet, monthlyNet }

gratuity({ lastDrawnWage, years, months = 0, covered = true,
           employeeType = "permanent", exemptionAlreadyUsed = 0 })
  → { amount, countedYears, eligible, minimumService, exempt, taxable }

hraExemption({ basic, da = 0, hraReceived, rentPaid, metro = false })
  → { exempt, taxable, limbs: { hraReceived, rentOverTenPercent, percentOfSalary } }

professionalTax(state, monthlySalary)   // state is a slug, e.g. "tamil-nadu"
  → { monthly, annual, levied, state }

statesWithProfessionalTax()             // → string[] of slugs

data.incomeTax, data.professionalTax    // the raw JSON, if you want the slabs
Not tax advice. Professional tax slabs in particular are revised in state budgets. Cross-check anything you rely on in payroll against the relevant state commercial-tax portal before it touches a real payslip.

The data, in the open

Income tax slabs — new regime, FY 2026-27

Standard deduction ₹75,000 · cess 4% · rebate under 87A up to ₹12,00,000 taxable, with marginal relief.

States that levy professional tax

Article 276 allows no more than ₹2,500 a year; the highest any state currently reaches is ₹2,496. States not listed here do not levy professional tax at all.

Where this comes from

The package is maintained by Klair Technology Solutions and backs the free calculators at klair.in — so the rules here are the same ones running in production, not a side project that quietly went stale. If you would rather use a calculator than a library:

Found a rule we have wrong? Open an issue — a failing test case is the most useful possible bug report.