# Payslip PDF to Excel & CSV (`adhistory/payslip-pdf-to-excel`) Actor

Turn payslip PDFs into rows: employee, pay period, gross pay, tax, deductions, net pay and every earnings and deduction line, plus one Excel file and CSVs. Billed per payslip delivered.

- **URL**: https://apify.com/adhistory/payslip-pdf-to-excel.md
- **Developed by:** [Brandon Ob](https://apify.com/adhistory) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 payslips

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Payslip PDF to Excel & CSV: net pay, gross pay, tax and deductions

This payslip PDF to Excel converter reads payslip (pay stub) PDFs and returns one row per payslip: employee, employee ID, employer, pay period, pay date, gross pay, tax, total deductions and net pay, plus every earnings row (hours, rate, amount) and deduction row. You also get one Excel file for the whole run (a Payslips sheet and an Earnings & deductions sheet) and two CSV files, so you can sort, filter and report without retyping. You are charged per payslip delivered, never for a PDF that failed or was not a payslip.

### What does Payslip PDF to Excel & CSV do?

- **Extracts payslip header fields**: employee name, employee ID, employer, period start and end, pay date, currency, gross pay, tax, total deductions and net pay.
- **Extracts every earnings and deduction line**: description and amount, plus hours and rate when the row has them (can be switched off).
- **Checks each payslip**: `checksOut` is `true` when gross pay minus total deductions equals net pay, so a misread number shows up instead of slipping into your workbook.
- Recognizes labels in **English**, with some **German, French and Spanish** ones ("Net pay", "Gross pay", "Netto", "Salaire net", "PAYE", "PAYG tax withheld" and more).
- Uses the current-period amount when a payslip also has a year-to-date column.
- Writes `payslips.xlsx`, `payslips.csv` and `earnings-and-deductions.csv` for the whole run, and opens password-protected PDFs with the password you give.
- Includes a **built-in sample payslip** (input `sample`) so you can see the output first.

### Use cases

- **Employees and contractors:** turn a year of payslips into one spreadsheet to check pay, tax and overtime.
- **Bookkeepers and payroll reviewers:** compare gross, tax and net pay across employees and periods without retyping.
- **Mortgage brokers and lenders:** summarize an applicant's recent payslips, with a check that the numbers add up.
- **HR teams:** audit overtime, allowances and deductions across exported payslips.
- **Automation builders:** add a "payslip to rows" step after a document upload, then send the rows to Google Sheets.

### How to use it

1. Open the Actor in Apify Console. The default input, `sample`, runs the built-in example; replace it with payslip PDF links, one per line. Each file must open in a browser without a login.
2. Optional: turn off **Extract earnings and deduction lines** if you only need the header fields and totals.
3. Click **Start**.
4. Open the **Payslips** view, download the dataset, or use the `excelUrl` workbook.
5. To process new payslips regularly, save your input as a task and schedule it, or call the Actor from the API.

### Input

| Field | What it does |
|---|---|
| `pdfUrls` | Direct links to payslip PDFs, one per line. `sample` runs the built-in example. |
| `extractLines` | Also read every earnings and deduction row (on by default). |
| `pdfPassword` | Optional; the same password is tried on every file. |
| `maxItems` | Stop after this many payslips (default 100). |

Example input:

```json
{
  "pdfUrls": ["sample"],
  "extractLines": true,
  "maxItems": 100
}
```

### Output

One dataset item per payslip. Real output from the default run (the synthetic sample payslip), shortened:

```json
{
  "employeeName": "Jordan A. Sample",
  "periodStart": "2026-10-01",
  "periodEnd": "2026-10-31",
  "payDate": "2026-10-30",
  "currency": "AUD",
  "grossPay": 5310.0,
  "tax": 1180.0,
  "totalDeductions": 1450.0,
  "netPay": 3860.0,
  "checksOut": true,
  "earnings": [
    {"description": "Ordinary hours", "amount": 4800.0, "hours": 160.0, "rate": 30.0},
    {"description": "Overtime", "amount": 360.0, "hours": 8.0, "rate": 45.0},
    {"description": "Allowances", "amount": 150.0}
  ],
  "deductions": [
    {"description": "PAYG tax withheld", "amount": 1180.0}
  ],
  "excelUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/payslips.xlsx"
}
```

Each item also has `employeeId`, `employer`, `pdfUrl`, `pages` and `extractedAt`. The key-value store holds `payslips.xlsx`, `payslips.csv`, `earnings-and-deductions.csv` and a `SUMMARY` record that lists PDFs that could not be read or were not payslips. The dataset can be downloaded as JSON, CSV, Excel, XML or HTML, or read through the API.

### Pricing

Pay per event: **$5.00 per 1,000 payslips** delivered, plus a $0.00005 charge per Actor start. PDFs that fail or are not payslips are not charged. You can set a maximum cost per run.

Discounts apply automatically on paid Apify plans: 10% off on Starter, 20% on Scale and 30% on Business.

Example: 12 monthly payslips cost about **$0.06**; 1,000 payslips for a small company's year cost about **$5.00**.

### Integrations and API

Run it and get the payslips back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/adhistory~payslip-pdf-to-excel/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"pdfUrls": ["https://example.com/payslip-oct.pdf"], "extractLines": true}'
```

Python, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("adhistory/payslip-pdf-to-excel").call(run_input={
    "pdfUrls": ["https://example.com/payslip-oct.pdf"],
})
for slip in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(slip["periodEnd"], slip["grossPay"], slip["netPay"], slip["checksOut"])
```

Like every Apify Actor, it also works with Make, Zapier and n8n, with webhooks and schedules, and as a tool for AI agents through the Apify MCP server.

### FAQ

**Does it read scanned payslips?** No. It needs PDFs that contain real text, such as exports from payroll software. A scanned payslip (a picture of paper) fails with a clear message; there is no OCR.

**A field is empty. Why?** The payslip probably uses a label the Actor does not know, or none. Open an issue with the layout (no private data needed) and I will add the label.

**How are dates handled?** Dates are returned as `YYYY-MM-DD` when the order of day and month is clear (for example `31/10/2026`). Ambiguous dates and dates with a month name are returned as printed.

**How reliable are the earnings and deduction lines?** They are a best effort. Rows with a description followed by numbers on one line work best. Multi-line descriptions and unusual column orders can split or merge rows; `checksOut` helps you spot problems.

**Does it connect to my payroll system?** No. It reads PDF files you provide. It does not connect to MYOB, Xero, QuickBooks or any payroll system.

**Is my data safe?** Files are processed in your own Apify run and results stay in your account's storage. Payslips are personal data: only submit files you are allowed to process. Up to 50 MB per PDF, from public links.

### Related tools

- [Bank Statement PDF to Excel & CSV](https://apify.com/adhistory/bank-statement-to-excel): transactions and balances from bank statements.
- [Invoice PDF to Excel & CSV](https://apify.com/adhistory/invoice-pdf-to-excel): invoice numbers, totals and line items.
- [PDF Table to Excel & CSV](https://apify.com/adhistory/pdf-tables-to-excel): every table from any text-based PDF.
- [Google Sheets Export & Import](https://apify.com/adhistory/google-sheets-export-actor): send payslip rows straight into a Google Sheet.

Found a bug or need a feature? Open an issue on the Issues tab — I usually reply within a day.

# Actor input Schema

## `pdfUrls` (type: `array`):

Direct links to payslip PDF files, one per line. The file must be reachable without a login. Enter the word sample to try a built-in example payslip.

## `extractLines` (type: `boolean`):

Also read every earnings row (hours, rate, amount) and deduction row. Turn off to get the header fields and totals only.

## `pdfPassword` (type: `string`):

Optional. Only for password-protected files; the same password is tried on every file.

## `maxItems` (type: `integer`):

Stop after this many payslips. You are charged per payslip delivered.

## Actor input object example

```json
{
  "pdfUrls": [
    "sample"
  ],
  "extractLines": true,
  "maxItems": 100
}
```

# Actor output Schema

## `payslips` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "pdfUrls": [
        "sample"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("adhistory/payslip-pdf-to-excel").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "pdfUrls": ["sample"] }

# Run the Actor and wait for it to finish
run = client.actor("adhistory/payslip-pdf-to-excel").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "pdfUrls": [
    "sample"
  ]
}' |
apify call adhistory/payslip-pdf-to-excel --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,adhistory/payslip-pdf-to-excel"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/BoWpbDf7bN3l2QGrl/builds/t4ffdnfrAQiyIWlAy/openapi.json
