How the South Africa salary after tax calculator is verified
Inputs
| Input | Field | Type |
|---|---|---|
| Gross annual salary (ZAR) | grossAnnual | number |
The formula
Each derived value below is computed by the Valem engine from the expression shown, in this order. Nothing else runs — there is no hidden code path.
| Derived value | Field | Formula (JSONata) |
|---|---|---|
| Paye Gross | payeGross | ($t := grossAnnual; $round((($t < 245100 ? $t : 245100) * 0.18) + (($t > 245100 ? (($t < 383100 ? $t : 383100) - 245100) : 0) * 0.26) + (($t > 383100 ? (($t < 530200 ? $t : 530200) - 383100) : 0) * 0.31) + (($t > 530200 ? (($t < 695800 ? $t : 695800) - 530200) : 0) * 0.36) + (($t > 695800 ? (($t < 887000 ? $t : 887000) - 695800) : 0) * 0.39) + (($t > 887000 ? (($t < 1878600 ? $t : 1878600) - 887000) : 0) * 0.41) + (($t > 1878600 ? ($t - 1878600) : 0) * 0.45), 2)) |
| PAYE (after rebate) | paye | ($p := payeGross - $const.primaryRebate; $round($p > 0 ? $p : 0, 2)) |
| UIF | uif | $round((grossAnnual < $const.uifCeiling ? grossAnnual : $const.uifCeiling) * $const.uifRate, 2) |
| Net / year | netAnnual | $round(grossAnnual - paye - uif, 2) |
| Net / month | netMonthly | $round(netAnnual / 12, 2) |
Rates and thresholds
The expressions above read these as $const. They are the figures the annual refresh replaces, so they live as data rather than being written into the formulas — which is what makes a year-on-year change a one-line diff instead of an edit to arithmetic.
| Constant | Value |
|---|---|
primaryRebate | 17820 |
uifRate | 0.01 |
uifCeiling | 212544 |
Test vectors (2)
Every case is executed against this model on each build, by the Java engine and independently by a JavaScript one. A mismatch of a single cent fails the build, so the page cannot ship advertising a figure the model no longer produces.
Case 1 — S1 360,000 ZAR single
given grossAnnual | 360000 |
|---|---|
expect paye | 56172 |
expect uif | 2125.44 |
expect netAnnual | 301702.56 |
Case 2 — S3 900,000 ZAR
given grossAnnual | 900000 |
|---|---|
expect paye | 247293 |
expect netAnnual | 650581.56 |
Sources
- SARS — tax tables · checked 2026-08-02
Check it yourself — and reuse it
The whole model as JSON — inputs, outputs, formulas, vectors and sources in one re-runnable document.
This model is published under CC BY 4.0: use it, adapt it, build on it, with attribution. The licence covers the model — the expression of each rule and the arrangement of the catalog. The rates and thresholds are law, and nobody licenses those; the sources above are where they come from.
← Back to the South Africa salary after tax calculator
Built with Valem — a live, verifiable calculator you can fork and embed.