The Tax Brief real effective rates for 111+ countries — bi-weekly, free.
API GUIDE

How to Calculate Take-Home Pay in Any Country via API

CountryTaxCalc Research Team · About Updated July 2026
Tax data in examples is for informational and product integration purposes only, sourced from official government tax authorities. Consumer-facing products must include appropriate disclaimers — see the API Terms of Service and Legal Disclaimer.
Quick answer: POST /api/v1/calculate returns totals.net_income, totals.effective_tax_rate, totals.monthly_net_income, and a full breakdown of income tax brackets and social contributions — in a single call, for any of 111 countries.

What the API returns

The POST /api/v1/calculate endpoint returns three things in every response: the totals (the numbers to display to users), the breakdown (the detailed tax logic), and the metadata (data provenance and confidence).

The totals object

This is what most products display directly to users:

  • net_income — annual take-home pay after all deductions
  • total_tax — sum of income tax + all social contributions
  • effective_tax_rate — total tax as a percentage of gross income
  • take_home_percentage — the inverse: percentage of gross income retained (100 − effective rate)
  • monthly_net_income — annual net divided by 12, pre-calculated for convenience
  • total_deductions — sum of all pre-tax deductions applied (personal allowances, etc.)

The breakdown object

This contains the detailed tax logic — useful if you want to show users how the number was reached:

  • deductions[] — named deductions applied before tax (e.g. Personal Allowance)
  • taxable_income — gross income minus deductions
  • national_income_tax — income tax amount, effective rate, marginal rate, and brackets applied
  • social_contributions[] — each social contribution (National Insurance, Medicare, etc.) with name, type, amount, and rate

The metadata object

For trust and compliance:

  • data_source — official government authority (e.g. "HMRC", "IRS")
  • last_updated — ISO date the rates were last verified
  • accuracy_confidence — 0.95 (DB-backed, verified) or 0.7 (simplified estimate)
  • calculation_date — ISO timestamp of the calculation

Step 1: Make the request

The minimum required fields are income and country. All other fields are optional.

curl -X POST https://api.countrytaxcalc.com/api/v1/calculate \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key_here" \
  -d '{
    "income": 60000,
    "country": "GB"
  }'

Optional fields you can add:

  • "currency": "USD" — income is in USD, convert to GBP before calculating
  • "jurisdiction": "CA" — for US states or Canadian provinces (US/CA only)
  • "tax_year": 2025 — historical year data (Growth+ plans only)

Country can be specified as an ISO 3166-1 alpha-2 code ("GB") or as a country name ("United Kingdom"). Country codes are preferred — they're unambiguous. Use GET /api/v1/countries (no key required) to get the complete list of valid codes.

Step 2: Parse the response

Here's how to extract the key values in JavaScript and Python:

JavaScript

const response = await fetch(
  "https://api.countrytaxcalc.com/api/v1/calculate",
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": process.env.COUNTRYTAXCALC_API_KEY
    },
    body: JSON.stringify({ income: 60000, country: "GB" })
  }
);

const data = await response.json();

// Core take-home values
const annualNetIncome = data.totals.net_income;         // 45357
const monthlyNetIncome = data.totals.monthly_net_income; // 3779.75
const effectiveTaxRate = data.totals.effective_tax_rate; // 24.41
const takeHomePercent = data.totals.take_home_percentage; // 75.59
const totalTax = data.totals.total_tax;                  // 14643

// Breakdown
const incomeTax = data.breakdown.national_income_tax.amount; // 11432
const marginalRate = data.breakdown.national_income_tax.marginal_rate; // 0.40

// Social contributions
const socialTax = data.breakdown.social_contributions
  .reduce((sum, c) => sum + c.amount, 0); // 3211

// Metadata
const confidence = data.metadata.accuracy_confidence; // 0.95
const source = data.metadata.data_source; // "HMRC"

Python

import requests

resp = requests.post(
    "https://api.countrytaxcalc.com/api/v1/calculate",
    headers={
        "Content-Type": "application/json",
        "X-API-Key": "your_api_key_here"
    },
    json={"income": 60000, "country": "GB"}
)

data = resp.json()
totals = data["totals"]
breakdown = data["breakdown"]

annual_net = totals["net_income"]          # 45357
monthly_net = totals["monthly_net_income"] # 3779.75
effective_rate = totals["effective_tax_rate"] # 24.41
total_tax = totals["total_tax"]            # 14643
income_tax = breakdown["national_income_tax"]["amount"] # 11432

# Social contributions as a dict
social = {
    c["name"]: c["amount"]
    for c in breakdown["social_contributions"]
}
# e.g. {"National Insurance": 3211}

Error handling

Always check the HTTP status code before parsing. The API uses standard codes:

  • 200 — success, parse response.json() normally
  • 400 — bad request (missing fields, invalid income value) — check error field
  • 401 — invalid or missing API key
  • 404 — country not found — use the countries list endpoint to validate codes
  • 422 — currency conversion failed (rare, obscure currency pairs)
  • 429 — rate limit exceeded — check retry_after_seconds or reset_at
  • 500 — internal error — retry with exponential backoff

Step 3: Display to users

The fields you choose to display depend on your product. Here are the most common display patterns:

Simple take-home calculator

Display totals.net_income and totals.effective_tax_rate. Add totals.monthly_net_income as a secondary figure. This is sufficient for most user-facing calculators.

// Minimal display
const netLabel = confidence >= 0.9
  ? `£${annualNetIncome.toLocaleString()}`
  : `~£${annualNetIncome.toLocaleString()} (estimated)`;

// Full card display
`Annual take-home: ${netLabel}
 Monthly: £${monthlyNetIncome.toLocaleString()}
 Effective tax rate: ${effectiveTaxRate}%
 You keep: ${takeHomePercent}% of gross`

Detailed breakdown view

For users who want to see how the number was calculated, render the breakdown object as a line-item list:

const displayBreakdown = [
  { label: "Gross income", amount: data.gross_income, bold: true },
  ...data.breakdown.deductions.map(d => ({
    label: d.name,
    amount: -d.amount,
    note: "deduction"
  })),
  { label: "Taxable income", amount: data.breakdown.taxable_income, note: "subtotal" },
  { label: "Income tax", amount: -data.breakdown.national_income_tax.amount },
  ...data.breakdown.social_contributions.map(c => ({
    label: c.name,
    amount: -c.amount
  })),
  { label: "Net take-home", amount: data.totals.net_income, bold: true }
];

Compliance requirement

Required under API Terms of Service: Any consumer-facing product must include a disclaimer stating that results are approximate and for informational purposes only. Recommended language: "Tax estimates are approximate. Consult a qualified tax professional for advice specific to your situation." This is a contractual requirement, not a suggestion.

Worked example: UK £60,000 salary (2026/27)

The following example uses verified HMRC 2026/27 rates. This is the exact response structure for a UK gross salary of £60,000.

// Request
POST /api/v1/calculate
{
  "income": 60000,
  "country": "GB"
}

// Response
{
  "country": "United Kingdom",
  "country_code": "GB",
  "tax_year": 2026,
  "currency": "GBP",
  "currency_symbol": "£",
  "gross_income": 60000,
  "breakdown": {
    "deductions": [
      { "name": "Personal Allowance", "amount": 12570 }
    ],
    "taxable_income": 47430,
    "national_income_tax": {
      "amount": 11432,
      "effective_rate": 0.1905,
      "marginal_rate": 0.40,
      "brackets_applied": [
        { "threshold": 0,     "rate": 0.20, "tax": 7540 },
        { "threshold": 50270, "rate": 0.40, "tax": 3892 }
      ]
    },
    "social_contributions": [
      {
        "name": "National Insurance",
        "type": "social_security",
        "amount": 3211,
        "rate": 0.08,
        "capped": false
      }
    ]
  },
  "totals": {
    "total_deductions": 12570,
    "total_tax": 14643,
    "net_income": 45357,
    "effective_tax_rate": 24.41,
    "take_home_percentage": 75.59,
    "monthly_net_income": 3779.75
  },
  "metadata": {
    "calculation_date": "2026-07-08T10:00:00.000Z",
    "data_source": "HMRC",
    "last_updated": "2026-04-06",
    "accuracy_confidence": 0.95
  }
}

How the numbers are calculated

UK income tax 2026/27:

  • Personal Allowance: £12,570 (tax-free)
  • Basic rate 20%: £12,571–£50,270 → on the first £37,700 of taxable income = £7,540
  • Higher rate 40%: £50,271–£60,000 → on £9,730 above the threshold = £3,892
  • Income tax total: £11,432

National Insurance (employee, 2026/27):

  • 8% on earnings £12,584–£50,284: £3,016 (rounded to nearest £)
  • 2% on earnings above £50,284: £195
  • NI total: £3,211

Total tax: £11,432 + £3,211 = £14,643. Net income: £60,000 − £14,643 = £45,357. Effective rate: £14,643 ÷ £60,000 = 24.41%.

Multi-country comparison

To compare take-home pay across multiple countries, call POST /calculate in a loop — one request per country. This is the approach available on all plan tiers. For the equivalent income in each country, use the currency field to convert from a single base currency.

// Compare UK vs Germany vs Netherlands at $80,000 USD equivalent
const countries = ["GB", "DE", "NL"];

const results = await Promise.all(
  countries.map(country =>
    fetch("https://api.countrytaxcalc.com/api/v1/calculate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-API-Key": process.env.COUNTRYTAXCALC_API_KEY
      },
      body: JSON.stringify({
        income: 80000,
        currency: "USD",  // convert to local currency before calculating
        country
      })
    }).then(r => r.json())
  )
);

// Sort by net income descending
results.sort((a, b) => b.totals.net_income - a.totals.net_income);

results.forEach(r => {
  console.log(
    `${r.country}: ${r.currency_symbol}${r.totals.net_income.toLocaleString()} ` +
    `net (${r.totals.effective_tax_rate}% effective)`
  );
});

Each response includes a currency_conversion object showing the exchange rate used, so you can display it transparently to users.

Pro tip — caching: Country+income+currency combinations are deterministic. Cache results server-side for up to 24 hours (permitted under the Terms of Service). If you're showing the same comparison to thousands of users, a cache layer means you make the API call once and serve the cached result to everyone else.

Disclaimers and accuracy notes

The take-home figures the API returns are accurate for the modelled tax position — a standard single resident taxpayer with the income specified. There are circumstances where the actual take-home will differ:

  • Filing status — the US, Germany, and several other countries have different rates for married filers. The API models single/standard by default.
  • Employer contributions — some countries (notably Germany, France, Netherlands) have significant employer social contributions on top of employee contributions. The API models employee-side only — what the employee receives, not the total employment cost to the employer.
  • Tax reliefs and deductions — pension contributions, mortgage interest relief, charitable giving, and other itemised deductions are not modelled. Users with significant deductions will have a lower actual tax bill.
  • Non-resident taxation — most API calculations assume standard resident tax treatment. Non-residents, dual residents, and expats often have different rates or treaty-based reductions.

These limitations are reflected in the metadata.accuracy_confidence field. Countries where the model is known to be a simplification return 0.7 confidence; countries with a full verified calculation return 0.95.

Frequently asked questions

Q: Does the API return monthly take-home pay as well as annual?

Yes. The response includes totals.monthly_net_income — the annual net income divided by 12. For the UK £60,000 example, that's £3,779.75/month. You don't need to calculate it yourself.

Q: How do I get the total tax burden including social contributions?

totals.total_tax is the sum of income tax plus all social contributions. It's always the right number to use for 'total deducted from pay'. If you need the split, breakdown.national_income_tax.amount gives you income tax alone, and you can sum breakdown.social_contributions[].amount for social insurance separately.

Q: What's the difference between effective_tax_rate and marginal_rate?

effective_tax_rate is the percentage of gross income paid in total tax (income tax + social contributions combined). marginal_rate inside breakdown.national_income_tax is the rate that applies to the next pound of income — useful for showing users how additional earnings will be taxed. The effective rate is almost always what you want to display to end users.

Q: What does take_home_percentage represent?

totals.take_home_percentage is simply 100 - effective_tax_rate. If the effective rate is 24.41%, take-home percentage is 75.59%. It's a convenience field for display — 'you keep 75.6% of your salary' is often more intuitive to users than the equivalent tax rate.

Q: What if the country has no income tax (UAE, for example)?

The API returns a valid full response with totals.total_tax: 0, totals.effective_tax_rate: 0, and totals.net_income equal to gross income. The breakdown object is still present but national_income_tax.amount and social_contributions will be zero. Zero-tax jurisdictions are fully supported — useful for relocation comparison tools where the 0% result is often the most compelling.

Q: How do I handle the accuracy_confidence field?

Check metadata.accuracy_confidence — values of 0.95 indicate a DB-backed calculation from verified official data. Values of 0.7 indicate a simplified fallback estimate. For consumer-facing products, we recommend labelling 0.7-confidence results as 'approximate' — for example, prefixing the net income with '~'. See the global coverage guide for a worked implementation example.

Q: Can I pass a filing status or number of dependents?

The current API models standard/default tax positions for each country. It does not accept filing status, marital status, number of dependents, or itemised deductions. The calculation assumes a single resident taxpayer with no special circumstances. This is accurate for most use cases but users with complex situations (married filing jointly in the US, for example) should be directed to a qualified tax professional.

Ready to integrate? 1,000 requests/month free. No credit card required.
Get your free API key →