Convert paystub PDF to Excel on Mac (2026 payroll guide)
Turn a year of paystub PDFs into one clean Excel sheet on Mac — on-device on macOS 14.4+, with gross, net, taxes, and YTD reconciled per pay period.
The mortgage broker wants the last twelve paystubs in a spreadsheet. Or the year is closing and you’re reconciling what your employer withheld against what the W-2 will eventually say. Or you run a five-person shop and your bookkeeper wants every employee’s gross-to-net broken out by pay period so the labor line in the P&L reconciles. Whatever the reason, you have a stack of paystub PDFs — downloaded one at a time from ADP, Gusto, Workday, or Paychex — and you need them as Excel rows, not as twenty-six separate two-page PDFs.
The single-stub case is trivial: you can read one paystub and type six numbers into a cell. The batch case is the one that eats a Saturday. Every provider lays the stub out differently. ADP buries year-to-date totals in a right-hand column; Gusto stacks earnings and deductions in two separate tables; Workday puts pre-tax and post-tax deductions in different sections that look identical at a glance. And the numbers you actually need — gross, each tax, each deduction, net, and the YTD running totals — are scattered across the page in boxes, not in one clean grid.
This guide is the Mac-native workflow: convert paystub PDFs to Excel on Mac, in batch, on-device on macOS 14.4+, with one consolidated sheet, one row per pay period, and YTD figures that reconcile across the year.
Why Mac (not iPhone) for a year of paystubs
A paystub lands on your iPhone the moment payroll runs — and for a single in-the-moment capture, the iPhone bank-statement flow shows the pattern that works on a phone. But consolidating a year of stubs is desk work, and the Mac wins for three concrete reasons:
- Drag a folder of twenty-six. A bi-weekly schedule is twenty-six stubs; semi-monthly is twenty-four; weekly is fifty-two. A folder of fifty-two PDFs is a Mac drag-and-drop, not a phone share sheet repeated fifty-two times.
- The big screen makes the YTD spot-check fast. The single most important paystub check — does the final stub’s YTD gross equal the sum of every period’s gross — is a glance on a 27-inch display with the workbook on one half and the December stub on the other.
- macOS 14.4+ on Apple Silicon keeps your SSN on the device. A paystub carries your full name, the last four of your SSN, sometimes your home address and employer EIN. On an M1-or-newer Mac running macOS 14.4+, the entire batch extracts locally — none of it is uploaded anywhere.
If your Mac is Intel-era (T2 or earlier), the on-device model isn’t available and ignitai falls back to a hosted pipeline with documented zero retention. For Apple Silicon Macs on macOS 14.4+, the whole year of stubs stays on the machine.
Why a paystub is harder to extract than it looks
“Paystub to Excel” sounds like one table. It is actually four regions, and a generic table extractor only catches one of them:
- Earnings. Regular hours, overtime, bonus, commission, PTO payout. Each has a rate, an hours figure, a current-period amount, and a YTD amount. Salaried stubs collapse the rate-and-hours columns; hourly stubs depend on them. Two columns of the same table mean two different things (this period vs. year-to-date), and they sit side by side.
- Taxes withheld. Federal income tax, Social Security (OASDI), Medicare, state income tax, and sometimes local or city tax, SDI, or SUI. Each is a current amount and a YTD amount. The labels vary by provider — “Fed Income Tax” vs “FITW” vs “Federal Withholding” all mean the same line.
- Deductions. Pre-tax (401(k), HSA, FSA, medical/dental premiums) and post-tax (Roth 401(k), garnishments, union dues). The pre-tax-vs-post-tax distinction matters for reconciling against the W-2 box 1, and most stubs separate them only by a small section header that a coordinate-based extractor ignores.
- Summary block. Gross pay, total taxes, total deductions, net pay — current and YTD. This is the reconciliation anchor, and it’s usually a small key-value block, not a row in any table.
A tool that grabs “all the tables” hands you a denormalized mess where this-period and YTD amounts blur together. A tool that understands a paystub as a paystub puts each earning, tax, and deduction in its own labeled column, keeps current and YTD separate, and gives you one row per pay period. That’s what you want in Excel, because the entire point is the year-end sum.
Method 1: ignitai on Mac (the on-device way)
ignitai treats paystub extraction as a language task — “read this stub and tell me the federal withholding” — not a grid-coordinate task. That’s why it survives the layout differences between ADP, Gusto, and Workday without per-provider templates. The full Mac batch flow:
-
Drag the folder of paystubs into ignitai. A year’s worth in one drop. Mixed providers are fine — if you changed jobs mid-year and have ADP stubs from January through June and Gusto stubs after, the same batch handles both. Up to 500 PDFs in one pass on an M-series Mac.
-
Describe what to extract, once for the whole batch. Plain English. A prompt that works across most US providers:
“For each paystub return one row: pay_date (ISO 8601), pay_period_start, pay_period_end, gross_pay, federal_tax, social_security, medicare, state_tax, pretax_deductions_total, posttax_deductions_total, net_pay, and the YTD figures ytd_gross, ytd_federal_tax, ytd_net. If a field is absent on a stub, leave it blank — do not guess.”
Save it as a preset. Next year it’s one click.
-
Pick XLSX as the output format. One sheet, one row per pay period, currency formatting auto-applied to the amount columns and ISO date formatting to the period columns.
-
Hit Extract. ignitai runs each PDF through the on-device model and streams rows into the workbook with live per-file progress. Fifty-two weekly stubs on an M2 Mac finish in two to three minutes.
-
Review the consolidated sheet. Every row carries a
source_filecolumn with the original PDF filename so you can trace any number back to its stub. Open in Excel for Mac or Numbers. -
Re-run failures, not the whole batch. Any stub that failed (a corrupted download, a password-protected PDF from a provider that encrypts) gets listed separately. Fix it, re-run just that file, append.
The whole year of pay data — every SSN fragment, every withholding figure — lives on your Mac. Nothing is uploaded.
Method 2: a Python script (the DIY path)
If every stub comes from one provider with a stable template and you want to own the pipeline:
pip install pdfplumber pandas openpyxl
Then a script that opens each PDF, pulls the summary numbers by text position, and writes one consolidated sheet:
import pdfplumber, pandas as pd, re
from pathlib import Path
rows = []
for pdf_path in sorted(Path("./paystubs").glob("*.pdf")):
with pdfplumber.open(pdf_path) as pdf:
text = "\n".join(p.extract_text() or "" for p in pdf.pages)
# provider-specific regex — this set matches one ADP layout only
gross = re.search(r"Gross Pay\s+([\d,]+\.\d{2})", text)
net = re.search(r"Net Pay\s+([\d,]+\.\d{2})", text)
rows.append({
"source_file": pdf_path.name,
"gross_pay": gross.group(1) if gross else None,
"net_pay": net.group(1) if net else None,
})
pd.DataFrame(rows).to_excel("paystubs.xlsx", index=False)
This works for one provider, one stable template, all text-based PDFs. It breaks the moment any of the following happens:
- The provider redesigns the stub. ADP and Gusto both push layout changes; your regex anchors silently stop matching and you get columns full of
None. - You changed jobs. New employer, new provider, new layout — a second regex set, maintained separately.
- A stub is a scan. Some employers hand out paper stubs; a photographed stub returns no text and
pdfplumbergives you nothing. You’d layer in OCR and accuracy drops on dense deduction tables. - The numbers you need aren’t in the summary. The moment you want per-deduction breakouts (401k vs HSA vs medical), the regex count explodes — one pattern per line item per provider.
For one-provider stability across a year, the script is a one-time cost. Across a job change or a multi-employee shop with different providers, the maintenance burden eats the savings.
Method 3: Preview + Numbers (the no-install fallback)
For two or three clean text-based stubs you don’t want to install anything for: open each PDF in Preview, select the summary block, Cmd-C, paste into Numbers, clean up the columns by hand, repeat per stub. It works for a handful of stubs from one provider with a simple grid. It falls apart on volume, on scans, and on any layout where the numbers aren’t in a clean rectangle — which is most of them. For a year of stubs, save the preset in Method 1 instead.
Method 4: web converters (and why not for paystubs)
Generic “PDF to Excel” web tools exist, and a paystub is exactly the document you should never put through one. You’d be uploading your full name, SSN fragment, home address, employer EIN, and twelve months of income to a server you don’t control. Free tiers gate at one to three files. And almost none are paystub-aware, so they smash the earnings, tax, and YTD regions into one denormalized table you then untangle by hand. For a tutorial stub with fake numbers, fine. For your actual pay history, no.
The reconciliation checks, on Mac
Once the sheet is written, three checks separate “I have a file” from “I have a payroll record I’d hand to a CPA or a lender”:
- YTD gross reconciliation. The final stub’s
ytd_grossshould equalSUMof every period’sgross_pay. Put=SUM(gross_pay_column)in a cell next to the last stub’s extracted YTD figure. A mismatch means a stub was missed, duplicated, or misread — this single check catches almost every extraction error. - Net = gross − taxes − deductions, per row. Add a column:
=gross_pay - (federal_tax + social_security + medicare + state_tax + pretax_deductions_total + posttax_deductions_total). It should equal the extractednet_payfor that row, to the cent. Any row that’s off flags a misread line on that specific stub. - Social Security sanity. OASDI is 6.2% of Social-Security-taxable wages up to the annual wage base.
social_security ÷ gross_payshould sit at or just under 0.062 on every row until you hit the wage base, then drop to zero. A row reading 0.062 of the wrong base is the fastest way to spot a gross figure that landed in the wrong column.
Skip these and the error surfaces during the mortgage underwriter’s review, or in April when the W-2 box 1 doesn’t match what you told the accountant.
What you do with the Excel sheet next
The consolidated workbook feeds whichever downstream job started this:
- Mortgage or rental application. Lenders want income verification across recent pay periods. One clean sheet with gross and net per period, plus the YTD anchor, is far easier for an underwriter than twenty-six separate PDFs — and you keep the PDFs as the source of truth alongside it.
- W-2 pre-check. In January, before the W-2 arrives, sum the year’s
federal_tax,social_security, andmedicare. When the W-2 shows up, boxes 2, 4, and 6 should match your totals. A mismatch is worth a payroll-department email before you file. This pairs naturally with the 1099 consolidation flow on Mac if you have contractor income too. - Small-business labor reconciliation. For a multi-employee shop, one row per employee per period lets the bookkeeper pivot
employee × month × grossand tie the labor line in the P&L to actual payroll runs. The broader mixed-document Mac batch pattern is in the Mac batch guide.
When this workflow doesn’t fit
Honest edge cases:
- Your provider already exports a register. ADP, Gusto, Workday, and Paychex all have a CSV/Excel payroll-register export in their admin portal. If you have admin access, use it — extracting from PDFs when the system will hand you a register is a workflow built backwards. The PDF path is for when you only have the stubs, which is the common case for employees rather than admins.
- You need only one number from one stub. Don’t build a batch for it. Open the stub, read the number, done.
- Stubs split earnings across multiple pages. Tighten the prompt: “earnings and deductions may continue onto a second page; treat both pages as one paystub, not two.” Save the preset, batch the rest.
Bottom line
For a folder of paystub PDFs that needs to become one Excel sheet on Mac — for a mortgage application, a W-2 pre-check, or a small-business labor reconciliation — install ignitai, drag the folder in, write the prompt once, pick XLSX, hit Extract, and run the three reconciliation checks. For a single-provider, stable-template year you want to own end to end, a pdfplumber-plus-pandas script is a valid alternative if you don’t mind maintaining the regex. For everything else — a job change mid-year, scanned stubs, multiple providers, or anything carrying an SSN you’d rather not upload — the on-device Mac batch is the shortest distance from a stack of stubs to a payroll record that reconciles.
The parallel bank-statement Mac flow (transactions instead of earnings) is in the Mac bank-statement guide; the annual tax-form consolidation is in the 1099 Mac guide. Same app, same presets, same on-device guarantee.
Get ignitai on the App Store — free download, $19.99/mo unlocks unlimited batch extractions after the 3-day trial.