# PDF Tables to Excel + True PII Redaction (MCP server) (`doubleaigents/pdf-tables-and-true-redaction-mcp`) Actor

Deterministic MCP tools for AI agents: extract tables from PDFs, scans and images to XLSX/CSV with every figure read twice and totals reconciled; truly redact personal data from PDFs (text removed, not covered) with a hashed log. No LLM inside.

- **URL**: https://apify.com/doubleaigents/pdf-tables-and-true-redaction-mcp.md
- **Developed by:** [Double AIgents](https://apify.com/doubleaigents) (community)
- **Categories:** AI, MCP servers, Developer tools
- **Features:** Limited permissions, Single-tenant, Server interface
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 page processed for table extractions

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## PDF Tables to Excel + True PII Redaction (MCP server)

Two deterministic document tools for AI agents, served as an MCP server. There is no LLM inside,
so the same file gives the same output every time. It runs on CPU and does not call any paid API.

**Use it for:** invoices, bank statements, price lists and financial reports into spreadsheets; anonymising
documents before disclosure, publication, sharing with a supplier or feeding to an LLM; removing personal data
from contracts, HR files, case bundles and FOI responses.

**Why agents pick it:** a figure the agent cannot trust is worse than no figure. Every number is double-read and
totals are reconciled, and every redaction is proven by re-extraction, so your agent gets a clear
`all_ok` / `verified` flag instead of guessing.

| Tool | What your agent gets back |
|---|---|
| `extract_tables` | Every table in a PDF, scanned PDF or image as rows (JSON), plus one XLSX with a sheet per table and a **Summary** sheet. Every numeric cell is read a **second time by an independent method**: pdfium reads the cell box for text PDFs, and a separate OCR pass reads each cell for scans. Column sums are **reconciled** against Subtotal/VAT/Total rows. `all_ok: false` means a figure or total disagrees, and the summary shows which. |
| `redact_pdf` | A redacted PDF where the matching text is **deleted from the page content stream**, not drawn over. Scanned pages are OCR'd and then rasterised with the boxes burned in. The output is **re-extracted by two text engines** to prove nothing that matches remains (`verified: true`). You also get a log CSV with page, type, salted hash, method and box. The log never contains the removed text. |

Built-in detectors: `email`, `phone_uk`, `phone_intl`, `postcode_uk`, `ni_number`, `iban` (checksum-validated), `sort_code`, `account_number`, and `date_of_birth` (dates near "DOB" or "date of birth"). Add your own `terms`, such as names, addresses or reference numbers, which are matched case-insensitively. Document metadata (author, title, XMP) and any annotations over redacted text are removed.

### Connect

MCP endpoint (streamable HTTP):

```
https://doubleaigents--pdf-tables-and-true-redaction-mcp.apify.actor/mcp
Authorization: Bearer <APIFY_TOKEN>
```

Claude Desktop / Cursor style config:

```json
{ "mcpServers": { "docengine": {
    "url": "https://doubleaigents--pdf-tables-and-true-redaction-mcp.apify.actor/mcp",
    "headers": { "Authorization": "Bearer <APIFY_TOKEN>" } } } }
```

Or through Apify's hosted MCP gateway, which handles auth for any MCP client:

```
https://mcp.apify.com?tools=doubleaigents/pdf-tables-and-true-redaction-mcp
```

Python (batch run with the Apify client):

```python
from apify_client import ApifyClient
run = ApifyClient("<APIFY_TOKEN>").actor("doubleaigents/pdf-tables-and-true-redaction-mcp").call(
    run_input={"operation": "extract_tables", "fileUrl": "https://example.com/report.pdf"})
print(run["defaultDatasetId"])
```

JavaScript:

```js
import { ApifyClient } from 'apify-client';
const run = await new ApifyClient({ token: '<APIFY_TOKEN>' })
  .actor('doubleaigents/pdf-tables-and-true-redaction-mcp')
  .call({ operation: 'redact_pdf', fileUrl: 'https://example.com/letter.pdf', terms: ['Jane Smith'] });
```

### Tool inputs

`extract_tables(file_url | file_base64, filename?, check=true, lang="eng")`

`redact_pdf(file_url | file_base64, filename?, terms=[], types=[all], ocr_text_layer=true, lang="eng")`

- Send exactly one of `file_url` (public http/https) or `file_base64`. Supported files are PDF, PNG, JPG, TIFF, BMP and WEBP, up to 50 MB and 500 pages.
- Output files come back as a key-value store URL. Files under 8 MB also come back inline as base64.

### Pricing (pay per event)

| Event | USD |
|---|---|
| `page-extracted`: each page processed by `extract_tables` | 0.02 |
| `page-redacted`: each page processed by `redact_pdf` (after verification) | 0.04 |
| `page-ocr`: extra charge for each scanned or image page | 0.01 |

You are charged only after a call completes. If your run's maximum charge cannot cover the page count, the call is refused before any work is done.

### Limits worth knowing

- Tables: ruled tables are detected directly. Unruled tables use a word-grid fallback that assumes one text line per row, so multi-line cells split into extra rows. Handwriting is not supported.
- Redaction: detection uses patterns plus your term list. It is not a named-entity model, so give it the names you need removed. Text inside images on otherwise text-based pages is not OCR'd. Rasterised pages get an OCR text layer, which can contain stray characters near the black boxes.
- Scans are OCR'd with Tesseract (English by default). Poor scans lower accuracy. When that happens, the second-pass check is what flags it.

### FAQ

**Is the redacted text really gone?** Yes. Text is removed from the page content, not covered with a box. The output is then re-extracted with two independent engines, and `verified` is true only if none of the redacted strings can be found.

**How do I know the table figures are right?** With `check=true` every numeric cell is read a second time independently and totals are reconciled. Any disagreement is listed, and `all_ok` is false.

**Does it use an LLM or send my file anywhere else?** No. It runs deterministic code (pdfplumber, pypdf, pdfium, Tesseract) inside the Actor. No third-party API is called.

**Can it handle scanned PDFs and photos?** Yes, with OCR, at $0.01 extra per scanned page. Accuracy depends on scan quality, and the second-pass check flags doubtful figures.

**What does a 10-page PDF cost?** Tables: $0.20. Redaction: $0.40. Add $0.10 if all 10 pages are scans.

### Batch mode

You can also run the Actor normally with `operation`, `fileUrl`, `terms` and the other inputs. It writes one dataset item, with links to the XLSX or redacted PDF and the log.

### Who runs it

Double AIgents Ltd, UK (company no. 17513072). Your input file is processed for the call and not kept by us. Outputs sit in the run's unnamed Apify storage, which Apify removes automatically under its data-retention policy.
Need volume pricing, a private deployment or a custom document pipeline? https://www.doubleaigents.com

### More tools from Double AIgents

- [Invoice & Receipt to JSON + Excel](https://apify.com/doubleaigents/invoice-receipt-to-json-mcp): supplier, dates, VAT and line items, with totals reconciled.
- [Bank Statement PDF to CSV/Excel](https://apify.com/doubleaigents/bank-statement-to-csv-mcp): every transaction, with running balances and opening/closing totals verified.
- [PDF Compare](https://apify.com/doubleaigents/pdf-compare-mcp): every added, removed or changed passage between two PDF versions, plus an annotated diff PDF.

# Actor input Schema

## `operation` (type: `string`):

extract_tables: tables to XLSX/CSV with a second-pass check. redact_pdf: true redaction with a log.

## `fileUrl` (type: `string`):

Public http(s) URL of a PDF, PNG, JPG or TIFF (max 50 MB, 500 pages).

## `terms` (type: `array`):

redact_pdf only. Case-insensitive names, addresses, reference numbers.

## `types` (type: `array`):

redact_pdf only. Leave empty for all: email, phone_uk, phone_intl, postcode_uk, ni_number, iban, sort_code, account_number, date_of_birth, term.

## `check` (type: `boolean`):

extract_tables only. Re-read every numeric cell independently and reconcile totals.

## `ocrTextLayer` (type: `boolean`):

redact_pdf only. Add an OCR text layer to pages that had to be rasterised.

## `lang` (type: `string`):

Tesseract language code. The image ships with eng.

## Actor input object example

```json
{
  "operation": "extract_tables",
  "fileUrl": "https://www.w3.org/WAI/WCAG21/working-examples/pdf-table/table.pdf",
  "terms": [],
  "types": [],
  "check": true,
  "ocrTextLayer": true,
  "lang": "eng"
}
```

# Actor output Schema

## `results` (type: `string`):

One row per run: operation, pages, ok/verified flag, link to the XLSX or redacted PDF, and the redaction log link.

## `files` (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 = {
    "fileUrl": "https://www.w3.org/WAI/WCAG21/working-examples/pdf-table/table.pdf"
};

// Run the Actor and wait for it to finish
const run = await client.actor("doubleaigents/pdf-tables-and-true-redaction-mcp").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 = { "fileUrl": "https://www.w3.org/WAI/WCAG21/working-examples/pdf-table/table.pdf" }

# Run the Actor and wait for it to finish
run = client.actor("doubleaigents/pdf-tables-and-true-redaction-mcp").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 '{
  "fileUrl": "https://www.w3.org/WAI/WCAG21/working-examples/pdf-table/table.pdf"
}' |
apify call doubleaigents/pdf-tables-and-true-redaction-mcp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,doubleaigents/pdf-tables-and-true-redaction-mcp"
        }
    }
}
```

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/g38rPJ37yPyagQHrX/builds/eV3kWLfRqHFzKlYbL/openapi.json
