# PDF Text Extractor — Text & Metadata from URLs (`darknezz/pdf-text-extractor`) Actor

Extract clean text and metadata from any PDF by URL: full text, page count, title, author, dates as JSON. Perfect for AI pipelines, RAG ingestion, document search and content analysis. No API key needed.

- **URL**: https://apify.com/darknezz/pdf-text-extractor.md
- **Developed by:** [Oaida Adrian](https://apify.com/darknezz) (community)
- **Categories:** Developer tools, AI
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 pdf extracteds

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 Text Extractor — Text & Metadata from Any PDF URL

Extract **clean plain text and full document metadata from any PDF** — just paste the URLs. No API keys, no login, no proxies, no OCR setup. Point it at a list of PDF links and get back structured, LLM-ready text plus title/author/date/page metadata for every file.

Built for developers and data teams who need to turn scattered PDF documents — research papers, financial reports, whitepapers, manuals, invoices, legal filings — into clean structured data at scale.

### Why this Actor

- **Zero configuration** — no credentials, no proxy budget, no browser. Paste URLs, press run.
- **RAG-ready output** — optional `includePageTexts` mode returns per-page text so you can chunk documents for embeddings without re-splitting.
- **Resilient by design** — unreadable or password-protected files are skipped and logged, never crashing the run. A batch of 500 PDFs with 3 bad links still returns 497 clean items.
- **Handles big documents** — multi-hundred-page files up to 100 MB each, including "secured" PDFs encrypted with an empty password.

### How it works

Give it a list of direct PDF URLs. For each file the Actor downloads it, parses it with a battle-tested PDF engine, and outputs **one dataset item per PDF** with the full extracted text and all document metadata. Set `maxPagesPerPdf` to cap long files, or `includePageTexts: true` to also get an array with each page's text separately.

### Input

```json
{
  "pdfUrls": [
    "https://arxiv.org/pdf/1706.03762",
    "https://bitcoin.org/bitcoin.pdf"
  ],
  "maxPagesPerPdf": 0,
  "includePageTexts": false
}
```

| Field | Type | Description |
|---|---|---|
| `pdfUrls` | array | Direct URLs of PDF files (**required**) |
| `maxPagesPerPdf` | integer | Max pages to extract per PDF; `0` = all pages |
| `includePageTexts` | boolean | Also output a per-page text array — ideal for RAG chunking |

### Output

One item per PDF:

```json
{
  "url": "https://arxiv.org/pdf/1706.03762",
  "fileName": "1706.03762",
  "fileSizeBytes": 2215244,
  "numPages": 15,
  "pagesExtracted": 15,
  "text": "Attention Is All You Need ...",
  "textLength": 39432,
  "wordCount": 6120,
  "title": "Attention Is All You Need",
  "author": null,
  "creator": "LaTeX with hyperref",
  "producer": "pdfTeX-1.40.25",
  "creationDate": "D:20240410010203Z",
  "modDate": null,
  "encrypted": false,
  "pageTexts": null
}
```

With `includePageTexts: true`, `pageTexts` becomes `["page 1 text...", "page 2 text...", ...]`.

### Use cases

- 🤖 **AI / RAG pipelines** — turn PDFs into LLM-ready text; use `pageTexts` as natural chunk boundaries for embeddings.
- 🔎 **Document search & indexing** — full text plus title/author/date metadata to power search over a PDF corpus.
- 📊 **Content & compliance analysis** — word counts, page counts, and document properties across large batches.
- 📚 **Bulk research ingestion** — pull hundreds of arXiv / SSRN papers or vendor whitepapers in one run.
- 🧾 **Report & invoice processing** — extract the text layer from financial reports, statements, and structured invoices.

### Run it from the API

Trigger the Actor and get results in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/darknezz~pdf-text-extractor/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pdfUrls":["https://bitcoin.org/bitcoin.pdf"],"includePageTexts":true}'
```

**Scheduling:** attach an Apify Schedule (e.g. hourly) to keep a folder of report URLs continuously ingested into a dataset that feeds your pipeline.

### Pricing

Pay per event: a small fee per PDF extracted, plus Apify's standard platform events (actor start + dataset item). Extracting 1,000 PDFs costs about **$5** in event fees — no monthly minimum, you pay only for what you run.

### FAQ

**Does it OCR scanned PDFs?** No — it extracts the embedded text layer. Scanned image-only PDFs return empty `text` (the item still includes metadata and page counts, so you can detect and route them to an OCR step).

**Password-protected PDFs?** Files encrypted with an empty password (common "secured" PDFs) are extracted automatically. User-password-protected files are skipped with a warning rather than failing the run.

**What's the file size limit?** 100 MB per file.

**Can I limit pages for very long documents?** Yes — set `maxPagesPerPdf` to any number; `0` extracts everything.

**Do I need a proxy?** No. The Actor downloads PDFs directly over HTTPS — no proxy or residential IP budget required.

**What if one URL is broken?** That file is skipped and logged; every other PDF in the batch still returns normally.

# Actor input Schema

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

Direct URLs of the PDF files to extract text from.

## `maxPagesPerPdf` (type: `integer`):

Maximum number of pages to extract per PDF. Set 0 to extract all pages.

## `includePageTexts` (type: `boolean`):

Also output an array with the text of each individual page (useful for chunking / RAG pipelines).

## Actor input object example

```json
{
  "pdfUrls": [
    "https://arxiv.org/pdf/1706.03762",
    "https://bitcoin.org/bitcoin.pdf"
  ],
  "maxPagesPerPdf": 0,
  "includePageTexts": false
}
```

# Actor output Schema

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

No description

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

No description

## `fileName` (type: `string`):

No description

## `fileSizeBytes` (type: `string`):

No description

## `numPages` (type: `string`):

No description

## `pagesExtracted` (type: `string`):

No description

## `textLength` (type: `string`):

No description

## `wordCount` (type: `string`):

No description

## `title` (type: `string`):

No description

## `author` (type: `string`):

No description

## `creationDate` (type: `string`):

No description

## `modDate` (type: `string`):

No description

## `encrypted` (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": [
        "https://arxiv.org/pdf/1706.03762",
        "https://bitcoin.org/bitcoin.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("darknezz/pdf-text-extractor").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": [
        "https://arxiv.org/pdf/1706.03762",
        "https://bitcoin.org/bitcoin.pdf",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("darknezz/pdf-text-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": [
    "https://arxiv.org/pdf/1706.03762",
    "https://bitcoin.org/bitcoin.pdf"
  ]
}' |
apify call darknezz/pdf-text-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=darknezz/pdf-text-extractor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/rbkAbMJ9H8aky1jNN/builds/voK8P7JsAxBz7pqGv/openapi.json
