Convert paystub PDF to Excel on Mac (2026 payroll guide)
Turn a year of paystub PDFs into one clean Excel sheet on Mac — stubs read on-device, never uploaded — gross, net, taxes, and YTD reconciled per pay period.
ignitai turns PDFs — even scans and photos — into clean Excel workbooks on your Mac — your first conversion is free, then $19.99/mo after a 3-day free trial.
Download on the App Store ignitai — free downloadThe 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 — stubs read on-device, never uploaded — 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 paystub flow covers that exact catch-it-when-it-lands path. But consolidating a year of stubs is desk work, and the Mac wins for three concrete reasons:
- Drop fifty-two files in one motion. A bi-weekly schedule is twenty-six stubs; semi-monthly is twenty-four; weekly is fifty-two. On the Mac that’s one ⌘A and one drag — 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.
- The stub files never leave your Mac. A paystub carries your full name, the last four of your SSN, sometimes your home address and employer EIN. ignitai reads each PDF on-device — the files are never uploaded — and sends only the recognized text to its private hosted pipeline to build the sheet.
On macOS 26, Apple’s newest on-device document recognition reads stub tables natively, which makes the earnings and deductions boxes extract noticeably sharper. On older versions (back to macOS 14.4), the same flow works with Apple’s classic on-device text recognition.
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 no-upload 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:
-
Select the paystubs and drag them 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.
-
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 — ISO dates and clean numeric text you format once in Excel (a currency format on the amount columns takes one click).
-
Hit Convert. ignitai reads each PDF on-device and builds the workbook with live progress — pages read, parts uploaded — across the batch. Fifty-two weekly stubs finish in a few minutes.
-
Review the consolidated sheet. The
pay_dateon every row ties each line back to its stub — the provider names the files by date, so any suspect number is one Spotlight search from its source PDF. Open in Excel for Mac or Numbers. -
If the batch trips, fix and re-run. A corrupted download or a password-protected PDF from a provider that encrypts stops the job. Unlock or re-download the offending stub and run the batch again.
The stub files themselves are never uploaded — each one is read on-device, and only the recognized text goes to ignitai’s private pipeline.
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, select the stubs and drag them in, write the prompt once, pick XLSX, hit Convert, 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.
FAQ
How do I consolidate a year of paystubs into Excel on a Mac?
Put the 24-52 stub PDFs in one folder, select them all, drag them into ignitai, and ask for one row per pay period with the columns you need. One prompt covers the whole year; the output is a single workbook, dated by pay period.
Are the paystubs uploaded anywhere?
No — each stub is read on the Mac (macOS 14.4 or later) and never uploaded. Only the recognized text is sent to ignitai’s private hosted pipeline to build the workbook.
What columns should I ask for in the prompt?
Pay date, gross, each withholding (federal, Social Security, Medicare, state), pre-tax and post-tax deductions separately, net, and the YTD figures. Then reconcile the final stub’s printed YTD gross against the sheet’s sum — one formula proves the whole year extracted cleanly.