The Local Tax Problem Nobody Warns You About

Most developers building payroll systems know about federal income tax and FICA. Some know about state income taxes. But the real complexity lives at the local level — and it catches almost everyone off guard.

There are 4,246 local jurisdictions in the US that levy some form of payroll-related tax. These include city income taxes, county occupational license taxes, school district levies, transit taxes, and special district assessments. And they stack.

An employee working in Columbus, Ohio and living in a different school district could owe:

That's five layers of tax from one paycheck. Now multiply by every employee in every location your payroll software handles.

Where Local Payroll Taxes Exist

Local payroll taxes are not evenly distributed across the US. They're concentrated in about 17 states, with the heaviest concentration in four:

Pennsylvania — 2,573+ Municipalities

Pennsylvania is the most complex state for local taxes. Under Act 32, every municipality and school district can levy an Earned Income Tax (EIT). Rates range from 0.5% to 3.6% (Philadelphia). Most non-resident rates are 1.0% under the standard Act 32 framework, but major cities have higher rates.

Each municipality is identified by a PSD (Political Subdivision Code), and tax collection is handled by regional Tax Collection Districts. Getting the right rate requires knowing the exact municipality — ZIP codes are not reliable because they cross municipal boundaries.

Ohio — 528+ Municipalities

Ohio has three different systems for local income tax collection, which makes it uniquely complex:

Some Ohio municipalities also levy school district income taxes, which are separate from the city income tax.

Kentucky — 133+ Counties and Cities

Kentucky's system is called the Occupational License Tax (OLT). All 120 counties can levy an OLT, and many cities levy their own on top of the county tax. Both stack — an employee working in Florence (city OLT: 2.0%) in Boone County (county OLT: 0.56%) owes both.

Rates changed across multiple jurisdictions between 2024-2026:

Indiana — 92 Counties

Every Indiana county levies a county income tax, with rates ranging from 0.5% (Porter County) to 3.0% (Randolph County). Several counties adjusted rates between 2024-2026, including Carroll, Grant, Greene, Howard, Shelby, and Union counties, all of which changed rates effective January 1, 2026.

Other States with Notable Local Taxes

Why Local Taxes Are Hard for Developers

1. Rates Change Frequently

Local tax rates change more often than federal or state rates, and with less notice. A city council can vote to raise their income tax rate mid-year. School district levies in Ohio go on the ballot every election cycle.

2. Boundaries Don't Match ZIP Codes

A single ZIP code can span multiple municipalities with different tax rates. The only reliable way to determine the correct jurisdiction is by street address — which requires geocoding or PSD code lookup.

3. Stacking Rules Vary by State

In Kentucky, city and county OLT taxes stack (you owe both). In Ohio, you generally owe tax only to the city where you work, with a credit against your residence city's tax. In Pennsylvania, the tax collection district determines which rate applies. Every state has different rules.

4. Resident vs. Non-Resident Rates Differ

Most local jurisdictions have different rates for residents vs. non-residents (people who work there but live elsewhere). Columbus, Ohio charges 2.5% to both, but many cities charge a lower rate to non-residents.

5. Reciprocity and Credits

If an employee lives in one city and works in another (both with income taxes), credit rules determine how much they owe each jurisdiction. These rules vary by state and sometimes by city.

How to Handle Local Taxes Programmatically

The traditional approach — maintaining spreadsheets of rates and manually updating them — breaks down at scale. Here's what works:

Use an API for Rate Lookups

Rather than maintaining your own database of 4,246 jurisdiction rates, query an API that stays current:

curl "https://payroll-tax-api-9f4b18020da9.herokuapp.com/v1/rates/lookup\
  ?workState=KY&workCity=Florence&workCounty=Boone\
  &payDate=2026-01-01" \
  -H "Authorization: Bearer ptx_free_your_key"

This returns both the Florence city OLT and Boone County OLT in a single response — correctly stacked.

Design for the Tax Stack

Your payroll system should model taxes as a stack, not a single rate. Every employee potentially owes multiple layers of local tax. Your data model needs to handle:

Track Effective Dates

Rates have effective dates. A rate that applies on January 1, 2026 may be different from what applied on December 31, 2025. Your system needs to query rates based on the pay date, not today's date.

The Scale of the Problem: 2024-2026

The local tax landscape continued to evolve across 2024-2026:

Tracking these changes across 4,246 jurisdictions annually is a full-time data maintenance operation. PayrollTax API handles this so you don't have to — get a free API key and start querying rates in seconds.