# PDF PII & Secret Redactor (`craigtechservicesllc/pdf-pii-secret-redactor`) Actor

Privately upload, detect, and permanently redact PII, payment details, tokens, and API secrets from text-based PDFs. No public source link, storage picker, broad account permission, or AI key required.

- **URL**: https://apify.com/craigtechservicesllc/pdf-pii-secret-redactor.md
- **Developed by:** [Daniel Craig](https://apify.com/craigtechservicesllc) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 document processeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## PDF PII & Secret Redactor

Remove common personal identifiers and credentials from text-based PDFs in bulk. The default secure browser workflow lets a user upload private files from the run's Live View without making them public or selecting an Apify storage resource. The Actor finds selected PII and secret types, applies real PDF redaction annotations, clears optional metadata and attachments, saves the sanitized PDF, and then reopens it to verify that matched text is no longer extractable.

This is a deterministic privacy utility, not an AI guesser and not a claim of legal compliance. It never places complete detected values in its dataset or logs.

### What it detects

- Email addresses
- International and North American phone-like numbers
- Validly structured U.S. Social Security numbers
- Payment-card numbers that pass the Luhn checksum
- IBANs that pass the MOD-97 checksum
- Valid IPv4 addresses
- JSON Web Tokens
- AWS access-key IDs
- API keys, client secrets, access tokens, and bearer tokens with an explicit label
- Up to 100 literal custom terms, such as a client name or case number

### Secure browser upload (recommended)

1. Leave **Secure browser upload** selected and start the Actor.
2. Open the running Actor's **Live View** tab.
3. Choose one or more PDFs, select detectors or custom terms, and click **Process selected PDFs**.
4. Save each redacted PDF. After the final save starts, the Actor run ends successfully on its own.

Apify does not currently auto-open an Actor's Live View after Start, so step 2 is required by the platform. **View in a new window** is optional.

Original browser uploads are read directly by the isolated run and processed in memory. They are not written to an input Key-value Store. Redacted PDF bytes are transferred directly into the browser and are not written to Actor storage either. Only a minimal report with generic document numbering and finding counts is saved. Live View downloads require the session's unguessable CSRF token; no permanent signed-public output URL is created for browser uploads.

The secure page has no external scripts, analytics, fonts, AI service, storage picker, or account-wide permission request. It closes after four minutes of inactivity or twenty minutes total.

### URL/API batch mode

For automations, select **Advanced URL/API batch** and provide authorized public or signed HTTPS PDF URLs. URL query strings are encrypted in Actor input and removed from dataset reporting. The downloader never attaches the Actor run token to a document request.

### What you get

URL/API batch mode writes a detailed document report containing finding counts, types, page and bounding-box evidence, warnings, a SHA-256 source fingerprint, and a signed link to the redacted PDF in run storage. Sensitive values are represented only by a masked hint and a SHA-256 digest.

Secure browser mode intentionally saves less: generic document numbering, counts, types, warnings, cleanup status, verification status, and billing fields. It does not save the original filename, source fingerprint, finding coordinates, matched-value hashes, or either PDF version. The redacted PDF is transferred into the browser during the live session.

The `OUTPUT` key contains the run summary. Redacted files use predictable keys such as `REDACTED-0001-contract.pdf`.

### Example input

```json
{
  "mode": "url_batch",
  "documents": [
    {
      "url": "https://example.org/authorized-contract.pdf",
      "name": "contract"
    }
  ],
  "action": "redact",
  "detectors": [
    "email",
    "phone",
    "ssn",
    "credit_card",
    "iban",
    "jwt",
    "aws_access_key",
    "api_secret"
  ],
  "customTerms": ["BLUE MARBLE"],
  "labelMode": "type",
  "removeMetadata": true,
  "stripAttachments": true
}
```

### Output example

```json
{
  "documentIndex": 1,
  "name": "contract.pdf",
  "status": "redacted",
  "pageCount": 12,
  "findingCount": 7,
  "findingTypes": {
    "email": 3,
    "phone": 2,
    "ssn": 2
  },
  "outputRecordKey": "REDACTED-0001-contract.pdf",
  "verification": {
    "performed": true,
    "passed": true,
    "remainingTextMatches": 0
  },
  "warnings": []
}
```

### Scan-only mode

Set `action` to `scan` to produce the same structured report without creating or changing a PDF. This is useful as a release gate in document workflows.

### Safety controls

- Only `http` and `https` PDF URLs are accepted.
- Local, private, link-local, reserved, multicast, credential-bearing, and nonstandard-port URLs are blocked to reduce SSRF risk.
- Redirect destinations are validated again.
- Downloads, document counts, page counts, and timeouts are bounded.
- Custom terms are escaped literal text; user-supplied regular expressions are not executed.
- Reports and error rows do not contain complete detected values.
- URL query strings and fragments are removed from result rows so signed-download parameters are not copied into the dataset.
- Secure browser uploads and their redacted outputs never enter a Key-value Store and never receive signed-public output URLs.
- The secure upload page uses bounded raw-body streaming, CSRF protection, no-store browser headers, a restrictive content-security policy, and no request-path logging.
- The Actor run token is never attached to document-download requests.
- Redact mode removes embedded attachments by default because their contents are not scanned.

### Important limitations

- Version 1 scans the PDF text layer. It does **not** perform OCR on scanned pages or redact text baked into images. Pages without extractable text are explicitly listed and warned about.
- Pattern matching can produce false positives or miss context-dependent PII. Review the output before publication or disclosure.
- Passwords entered in Live View exist only in the running container's memory. Passwords supplied in URL/API input are encrypted with the Actor input. In both cases, use short-lived document-specific passwords, never an account password.
- The Actor is a technical aid, not legal advice, a certification, or a guarantee of GDPR, HIPAA, CCPA, FOIA, or other compliance.
- Process only documents you are authorized to access and modify.

### Support

When filing an issue, include the run ID, whether the affected page has selectable text, and a non-sensitive sample if possible. Never paste private information or credentials into a public issue.

# Actor input Schema

## `mode` (type: `string`):

Secure browser upload is recommended. After starting the run, open Live View, choose PDFs from your computer, process them, and save the results. The run ends automatically after the final save. URL/API batch mode is intended for automations using authorized public or signed URLs.

## `documents` (type: `array`):

Used only when Advanced URL/API batch mode is selected. Supply authorized public or signed PDF URLs with optional output names and document-specific passwords. Private networks, URL credentials, and non-PDF responses are blocked.

## `action` (type: `string`):

Default for URL/API runs and the initial Live View form. Redact creates a cleaned PDF; Scan only returns a findings report.

## `detectors` (type: `array`):

Choose the deterministic detectors to run.

## `customTerms` (type: `array`):

Optional literal names, case numbers, project codes, or other exact text to remove. Regular expressions are not accepted.

## `customTermsCaseSensitive` (type: `boolean`):

Match custom exact terms using capitalization exactly as entered.

## `labelMode` (type: `string`):

Choose whether redaction boxes show the detected data type or remain plain black.

## `removeMetadata` (type: `boolean`):

Clear title, author, subject, keywords, and similar document metadata in redact mode.

## `stripAttachments` (type: `boolean`):

Embedded files are not scanned. Remove them from redacted output by default.

## `maxFileSizeMb` (type: `integer`):

Reject any input PDF larger than this many megabytes.

## `maxPagesPerDocument` (type: `integer`):

Reject any input PDF containing more than this number of pages.

## `downloadTimeoutSeconds` (type: `integer`):

Maximum time allowed to download each input PDF.

## Actor input object example

```json
{
  "mode": "secure_upload",
  "action": "redact",
  "detectors": [
    "email",
    "phone",
    "ssn",
    "credit_card",
    "iban",
    "ipv4",
    "jwt",
    "aws_access_key",
    "api_secret"
  ],
  "customTerms": [],
  "customTermsCaseSensitive": false,
  "labelMode": "type",
  "removeMetadata": true,
  "stripAttachments": true,
  "maxFileSizeMb": 25,
  "maxPagesPerDocument": 500,
  "downloadTimeoutSeconds": 30
}
```

# Actor output Schema

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

No description

## `files` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("craigtechservicesllc/pdf-pii-secret-redactor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("craigtechservicesllc/pdf-pii-secret-redactor").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 '{}' |
apify call craigtechservicesllc/pdf-pii-secret-redactor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,craigtechservicesllc/pdf-pii-secret-redactor"
        }
    }
}

```

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/5B1zz5g6nk6u2Xcoh/builds/67vUyBz6ag7GaNHOU/openapi.json
