# PDF Evidence Reader (`l3digital/pdf-evidence-reader`) Actor

Retrieve bounded page-cited passages for literal terms in one public PDF.

- **URL**: https://apify.com/l3digital/pdf-evidence-reader.md
- **Developed by:** [L3Digital](https://apify.com/l3digital) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.05 / useful report

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/actors/running/actors-in-store.md#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

### What does PDF Evidence Reader do?

PDF Evidence Reader retrieves compact, **page-cited passages** for one to five literal search terms in a public HTTPS PDF. It gives agents a bounded JSON report without generating an answer, running OCR, interpreting regular expressions, or dumping the whole document.

The Actor examines embedded text in PDFs up to 10 MiB and 100 physical pages. Each report includes a SHA-256 digest, redacted retrieval provenance, examined-page coverage, and explicit truncation or document-state signals.

### When should an agent select this tool?

Use it when the agent already has a public PDF URL and literal terms, and needs short inspectable passages with physical page citations. Use a different tool for OCR, semantic search, full-document extraction or generated answers. A local PDF parser remains an alternative for agents with code execution.

### Use from an AI agent through MCP

Add this URL to a client that supports remote HTTP MCP servers, then authorize with your own Apify account:

```text
https://mcp.apify.com/?tools=l3digital/pdf-evidence-reader
```

This selects the Actor directly instead of relying on search ranking. Follow the [Apify MCP setup guide](https://docs.apify.com/integrations/mcp) for your client. Ask your agent to call `l3digital/pdf-evidence-reader` with the example input below. If the MCP response returns a running job, follow its `nextStep` to retrieve the completed dataset; an accepted run is not yet a report. Calls use the pricing described below.

### Why use PDF Evidence Reader?

- Retrieve several terms in one Actor/API call.
- Keep passage text within a caller-selected aggregate character budget.
- Cite one-based physical PDF page numbers.
- Distinguish no matches, likely scanned/image-only PDFs, encryption, truncation, and safe acquisition/parser errors.
- Prevent access to private networks through URL, DNS-answer, redirect, and connected-peer checks.

It is designed for agents that need inspectable evidence rather than a generated conclusion. A caller must still judge source authority, meaning, and reuse rights.

### What data can PDF Evidence Reader extract?

| Field | Type | Description |
| --- | --- | --- |
| `status` | string | `ok`, `partial`, `no_matches`, `scan_needed`, `encrypted`, or `error` |
| `passages` | array | Page number, bounded text, and terms found in that passage |
| `matchedTerms` | array | Requested terms represented in returned passages |
| `coverage` | object | Pages examined and every relevant truncation signal |
| `provenance` | object | Redacted URLs, exact byte count, SHA-256, and hop counts |

### How to retrieve page-cited PDF evidence

1. Supply a direct public `https://` PDF URL. URLs with credentials or explicit ports are rejected.
2. Add one to five literal terms. Matching ignores case; terms are never treated as regex.
3. Optionally reduce `maxPassages` from 10 or `maxOutputCharacters` from 12,000.
4. Run the Actor and read the single item in the default dataset.
5. Check `status`, `coverage`, and `truncated` before using any passage.

```json
{
  "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "searchTerms": ["Dummy", "PDF"]
}
```

### Demo: locate terms in a longer public document

```json
{
  "url": "https://www.irs.gov/pub/irs-pdf/fw9.pdf",
  "searchTerms": [
    "certification",
    "exempt payee"
  ],
  "maxPassages": 5,
  "maxOutputCharacters": 2000
}
```

An internal validation run on 2026-09-06 examined six pages and returned four passages totaling 1,923 characters. The report was `partial` with `characterLimitReached: true`; the first passage cited physical page 1. This is a passage-location example, not tax advice. The source file can change.

An agent should cite the returned page and provenance, disclose truncation, and narrow its terms or increase its budget when more evidence is needed. A no-match result is limited to the reported extraction coverage; it does not prove a claim is absent from every part of the document. A useful partial report carries the same $0.05 charge.

### Input

See the input tab for the full schema. PDFs must be publicly reachable over standard-port HTTPS, at most 10 MiB, at most 100 pages for complete page coverage, unencrypted, and contain embedded text. Redirect destinations receive the same checks. Query strings may be used for acquisition but are removed from report provenance.

### Output

You can download the dataset in formats such as JSON, HTML, CSV, or Excel. The Actor writes exactly one versioned report for an accepted input, including expected failure states.

Observed output excerpt from the W3C test PDF in an internal run on 2026-09-06 (the full dataset contains all schema fields):

```json
{
  "schemaVersion": "pdf-evidence-reader/v1",
  "status": "ok",
  "passages": [
    {
      "pageNumber": 1,
      "text": "Dummy PDF file",
      "matchedTerms": [
        "Dummy",
        "PDF"
      ]
    }
  ],
  "totalPassageCharacters": 14,
  "truncated": false,
  "coverage": {
    "pagesDeclared": 1,
    "pagesExamined": 1,
    "pagesWithText": 1,
    "pageLimitReached": false,
    "extractionTextTruncated": false,
    "passageLimitReached": false,
    "characterLimitReached": false,
    "complete": true
  }
}
```

`scan_needed` means no embedded text was found in the examined pages; the Actor does not perform OCR. `complete` describes page/extraction coverage, not factual completeness or source authority.
`partial` means useful passages were returned but a page, extraction, passage, or character limit reduced coverage.

### How much does PDF evidence retrieval cost?

The price is **$0.05 per useful report**, charged once after the report is stored. Both `ok` and `partial` reports containing passages qualify for the custom event, including results truncated by caller-selected limits. No-match results, invalid inputs, and technical or document errors are free of the custom report charge. There are no separate start or dataset-item charges. The Store pricing tab is authoritative.

### Privacy, security, and support

The Actor sends a fixed unauthenticated GET request only to the caller-provided public PDF host and validated redirects. It does not forward cookies, authorization headers, Actor credentials, or environment proxy settings. Retrieved document text appears only in bounded result passages; source bytes are temporary and deleted after parsing.

Use only documents you may lawfully retrieve and process. Public availability does not establish authority, ownership, accuracy, or reuse rights. Results can contain personal data present in public documents; ensure you have a legitimate purpose and follow applicable privacy law. Use the Actor Issues tab for defects and the API tab for programmatic calls.

# Actor input Schema

## `url` (type: `string`):

Public HTTPS PDF URL. Credentials, explicit ports, and private network targets are rejected.

## `searchTerms` (type: `array`):

One to five case-insensitive literal terms. Regular expressions are not interpreted.

## `maxPassages` (type: `integer`):

Maximum number of page-cited passages returned.

## `maxOutputCharacters` (type: `integer`):

Aggregate character budget across returned passage text.

## Actor input object example

```json
{
  "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "searchTerms": [
    "Dummy",
    "PDF"
  ],
  "maxPassages": 10,
  "maxOutputCharacters": 12000
}
```

# Actor output Schema

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

The default dataset contains one report for the requested PDF.

# 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 = {
    "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "searchTerms": [
        "Dummy",
        "PDF"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("l3digital/pdf-evidence-reader").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 = {
    "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
    "searchTerms": [
        "Dummy",
        "PDF",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("l3digital/pdf-evidence-reader").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 '{
  "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "searchTerms": [
    "Dummy",
    "PDF"
  ]
}' |
apify call l3digital/pdf-evidence-reader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,l3digital/pdf-evidence-reader"
        }
    }
}
```

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/0X6tbKaZC0v4a0VZf/builds/mM7Lswq7aCp45umop/openapi.json
