# PDF Text Extractor (`parsebird/pdf-text-extractor`) Actor

Extract text and metadata from PDF files by URL: title, author, page-by-page text, embedded metadata, and optional Markdown conversion.

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

## Pricing

from $1.50 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 — Extract Text & Metadata from PDF Files by URL

Extract embedded text and metadata from any PDF file by URL. Get the document title, author, creation and modification dates, full text, a page-by-page breakdown, and an optional Markdown conversion — no manual parsing, no PDF library setup required. Export as JSON, CSV, or Excel.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Send a list of PDF URLs and get back structured text, document metadata, and per-page content in seconds — with an optional Markdown output ready for LLMs, RAG pipelines, and documentation tools.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

```
Apify Actor: parsebird/pdf-text-extractor — extracts embedded text and metadata from PDF files by URL. Two pay-per-event charges: pdf-extracted at $0.00299/result on the Free plan ($2.99/1000), $0.00259/result on Bronze ($2.59/1000), $0.00219/result on Silver ($2.19/1000), $0.0015/result on Gold ($1.50/1000); markdown-generated (only when convertToMarkdown is enabled) at $0.0005/result on Free/Bronze/Silver ($0.50/1000), $0.0004/result on Gold ($0.40/1000). Call via ApifyClient: client.actor("parsebird/pdf-text-extractor").call(run_input={"urls": ["https://example.com/report.pdf"], "includePages": true, "convertToMarkdown": false, "maxConcurrency": 3, "timeoutPerPdfSecs": 60}). Inputs: urls (array of strings, required — direct URLs to PDF files), includePages (boolean, default true — include per-page text breakdown), convertToMarkdown (boolean, default false — also generate a Markdown version of each PDF; skipped for PDFs over 25MB or 500 pages), maxConcurrency (integer, default 3, 1-10 — parallel PDF downloads), timeoutPerPdfSecs (integer, default 60 — download timeout per PDF in seconds). PDFs over 70MB are skipped with an error instead of being downloaded in full. Output: dataset with url, fileName, title, author, subject, keywords, creator, producer, creationDate, modificationDate, pageCount, fullText, pages (array of {pageNumber, text}), markdown (if enabled and under the size/page limit), pdfVersion, fileSizeBytes, error. No OCR — extracts embedded text only; scanned PDFs with no selectable text return empty text. API docs: https://docs.apify.com/api/v2 Token: https://console.apify.com/settings/integrations
```

### What does PDF Text Extractor do?

**PDF Text Extractor** is an [Apify Actor](https://apify.com/actors) that downloads PDF files from URLs you provide and extracts their embedded text and metadata — no need to install or maintain a PDF parsing library yourself.

- 📄 **Full text and metadata** — title, author, subject, keywords, creator, producer, creation/modification dates, page count, and PDF version
- 📑 **Per-page breakdown** — get text split by page, in addition to the full document text
- 📝 **Optional Markdown conversion** — turn each PDF into clean Markdown (headings, lists, basic formatting preserved), ready for LLM ingestion, RAG pipelines, or documentation sites
- ⚡ **Concurrent downloads** — process multiple PDFs in parallel with configurable concurrency (1-10) and a per-file download timeout
- 🛡️ **Per-file error handling** — a broken link or password-protected PDF doesn't stop the run; every URL gets its own result with an `error` field
- ⏱️ **Scheduling & API access** — run on autopilot with [Apify Schedules](https://docs.apify.com/platform/schedules) and pull results via the [Apify API](https://docs.apify.com/api/v2) or client libraries
- 📊 **Multiple export formats** — download as JSON, CSV, Excel, XML, or HTML

This Actor extracts **embedded text only** — it does not perform OCR (Optical Character Recognition). Scanned PDFs that contain only images, with no selectable text layer, will return an empty `fullText`.

### What data can you extract from a PDF?

| Field | Description |
|-------|-------------|
| `url` | The source URL of the PDF |
| `fileName` | File name parsed from the URL |
| `title` | Document title from PDF metadata |
| `author` | Document author from PDF metadata |
| `subject` | Document subject from PDF metadata |
| `keywords` | Document keywords from PDF metadata |
| `creator` | Application that created the source document |
| `producer` | Application that produced the PDF |
| `creationDate` | Document creation date |
| `modificationDate` | Document last-modified date |
| `pageCount` | Total number of pages |
| `fullText` | Full extracted text of the document |
| `pages` | Per-page text breakdown (when `includePages` is enabled) |
| `markdown` | Markdown version of the document (when `convertToMarkdown` is enabled) |
| `pdfVersion` | PDF format version (e.g. "1.6") |
| `fileSizeBytes` | Downloaded file size in bytes |
| `error` | Error message if the PDF could not be downloaded or parsed, otherwise `null` |

### How to use PDF Text Extractor

1. Go to **PDF Text Extractor** on [Apify Store](https://apify.com/parsebird/pdf-text-extractor) and click **Try for free**
2. Paste one or more direct PDF URLs into the **PDF URLs** field
3. Toggle **Include per-page text** on or off depending on whether you need a page-by-page breakdown
4. Toggle **Convert to Markdown** on if you want a Markdown version of each document
5. Adjust **Max concurrency** and **Timeout per PDF** if needed — the defaults work for most runs
6. Click **Start** and wait for the run to finish
7. Export your data as JSON, CSV, or Excel, or access it via the [Apify API](https://docs.apify.com/api/v2)

### Input parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `urls` | array | **Yes** | — | Direct URLs to PDF files |
| `includePages` | boolean | No | `true` | Include per-page text breakdown |
| `convertToMarkdown` | boolean | No | `false` | Also generate a Markdown version of each PDF |
| `maxConcurrency` | integer | No | `3` | Parallel PDF downloads (1-10) |
| `timeoutPerPdfSecs` | integer | No | `60` | Download timeout per PDF in seconds |

PDFs over 70MB are skipped with an error before being fully downloaded. Markdown conversion (`convertToMarkdown`) is additionally skipped — with text and metadata still returned — for PDFs over 25MB or 500 pages.

**Minimal input:**

```json
{
  "urls": ["https://example.com/document.pdf"]
}
```

### Output example

```json
{
  "url": "https://www.orimi.com/pdf-test.pdf",
  "fileName": "pdf-test.pdf",
  "title": "PDF Test Page",
  "author": "Yukon Department of Education",
  "subject": null,
  "keywords": null,
  "creator": "Acrobat PDFMaker 7.0.7 for Word",
  "producer": "Acrobat Distiller 7.0.5 (Windows)",
  "creationDate": "2008-06-04T15:44:00.000Z",
  "modificationDate": "2008-06-04T15:47:36.000Z",
  "pageCount": 1,
  "fullText": "PDF Test File  Congratulations, your computer is equipped with a PDF reader...",
  "pages": [
    {
      "pageNumber": 1,
      "text": "PDF Test File  Congratulations, your computer is equipped with a PDF reader..."
    }
  ],
  "pdfVersion": "1.6",
  "fileSizeBytes": 20597,
  "error": null
}
```

With `convertToMarkdown` enabled, each item also includes a `markdown` field containing the document converted to Markdown.

Download results in JSON, CSV, Excel, XML, or HTML, or access via the [Apify API](https://docs.apify.com/api/v2).

### Use cases

- 🤖 **LLM & RAG pipelines** — feed clean text or Markdown from PDF reports, whitepapers, and manuals into an embedding or retrieval pipeline
- 🧾 **Invoice and document processing** — pull text from invoices, contracts, or forms for downstream parsing
- 📚 **Knowledge base ingestion** — convert PDF documentation into Markdown for static sites, wikis, or search indexes
- 🔍 **Content auditing** — extract metadata (author, creation date, producer) across a batch of PDFs for compliance or provenance checks
- 🔌 **Pipeline integration** — feed extracted text into Google Sheets, Slack, Zapier, Make, or custom systems via [Apify Integrations](https://docs.apify.com/platform/integrations)

### How it works

1. The Actor downloads each URL in `urls`, up to `maxConcurrency` in parallel, respecting `timeoutPerPdfSecs` per file
2. It verifies the downloaded file is a valid PDF, then parses embedded text and metadata directly from the PDF structure — no OCR is performed
3. If `includePages` is enabled, text is also broken down per page
4. If `convertToMarkdown` is enabled, the Actor additionally converts the document to Markdown, preserving headings, lists, and basic formatting
5. Every result is pushed to the dataset as soon as it's ready — including failed URLs, which get an `error` message instead of stopping the run

### How to use via API — Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("parsebird/pdf-text-extractor").call(run_input={
    "urls": [
        "https://example.com/report-2024.pdf",
        "https://example.com/whitepaper.pdf",
    ],
    "includePages": True,
    "convertToMarkdown": True,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["error"]:
        print(f"Failed: {item['url']} — {item['error']}")
    else:
        print(f"{item['fileName']}: {item['pageCount']} pages, {len(item['fullText'])} chars")
```

### How to use via API — JavaScript

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

const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });

const run = await client.actor('parsebird/pdf-text-extractor').call({
    urls: [
        'https://example.com/report-2024.pdf',
        'https://example.com/whitepaper.pdf',
    ],
    includePages: true,
    convertToMarkdown: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    if (item.error) {
        console.log(`Failed: ${item.url} — ${item.error}`);
    } else {
        console.log(`${item.fileName}: ${item.pageCount} pages, ${item.fullText.length} chars`);
    }
});
```

### How much does it cost to extract text from PDFs?

PDF Text Extractor uses [pay-per-event pricing](https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event) with two separate events: one for text extraction, and one for Markdown conversion (only charged when `convertToMarkdown` is enabled). Platform usage (compute, bandwidth) is not charged separately.

**How much does it cost to extract text from 1,000 PDFs?**

$2.99 on the Free plan, $2.59 on Bronze, $2.19 on Silver, or $1.50 on Gold — plus $0.50 ($0.40 on Gold) per 1,000 if you also enable Markdown conversion. New users get a free trial with platform credit to try the Actor before committing.

**How much does it cost to extract text from 100 PDFs?**

Around $0.30 on the Free plan for text extraction alone, or about $0.35 with Markdown conversion enabled.

### Pricing

| Event | Price per event | Price per 1,000 |
|-------|------------------|------------------|
| `pdf-extracted` | $0.00299 (Free) / $0.00259 (Bronze) / $0.00219 (Silver) / $0.0015 (Gold) | **$2.99 / $2.59 / $2.19 / $1.50** |
| `markdown-generated` | $0.0005 (Free/Bronze/Silver) / $0.0004 (Gold) | **$0.50 / $0.40** |

`pdf-extracted` fires once per PDF successfully downloaded and parsed. `markdown-generated` fires once per PDF only when `convertToMarkdown` is enabled and a Markdown version was produced. Failed downloads are not charged.

### Is it legal to use PDF Text Extractor?

This Actor only downloads and processes PDF files at URLs you explicitly provide — it does not crawl or discover content on its own. You are responsible for ensuring you have the right to download and process the documents you submit, and for complying with any applicable copyright, privacy, or data protection laws in your jurisdiction.

### Related Actors

Looking for more content extraction and data processing tools? Check out these ParseBird actors:

- [X/Twitter Article Markdown API](https://apify.com/parsebird/x-twitter-article-markdown) — Convert X/Twitter articles and tweets to Markdown by tweet ID
- [HTTP Request](https://apify.com/parsebird/http-request-actor) — Send API calls and forward responses to webhooks from the cloud
- [Data Cleaner](https://apify.com/parsebird/data-cleaner) — Clean, normalize, and format scraped or extracted data
- [Data Deduplicator](https://apify.com/parsebird/dataset-deduplicator) — Merge and deduplicate Apify datasets by any field combination

Browse all [ParseBird actors on Apify Store](https://apify.com/parsebird).

### FAQ

**Does it work with scanned PDFs?**
No. This Actor extracts embedded text from PDFs. Scanned documents that contain only images (no selectable text) will return empty text. For scanned PDFs, you would need an OCR (Optical Character Recognition) solution.

**What happens if a PDF URL is broken or returns an error?**
That item is pushed to the dataset with `error` set to a descriptive message (e.g. "HTTP 404 while downloading PDF") and all other fields set to `null`. The run continues processing the remaining URLs — one bad link never stops the batch. Failed items are not charged.

**What happens with password-protected PDFs?**
The item is returned with `error: "PDF is password-protected"`. This Actor does not attempt to guess or brute-force passwords.

**What does `convertToMarkdown` actually convert?**
It runs the PDF through a Markdown converter that preserves structural elements like headings and lists where they're detectable in the PDF layout, in addition to the plain-text `fullText` and `pages` output.

**Does `includePages: false` remove `fullText` too?**
No. `fullText` (the full document text) is always included. `includePages` only controls whether the additional `pages` array with a per-page breakdown is included.

**What does `maxConcurrency` control?**
How many PDFs are downloaded and processed in parallel. Higher values finish large batches faster; lower values are gentler on the source server and use less memory per run.

**Is there a maximum PDF size?**
Yes. PDFs over 70MB are skipped with an `error` before being fully downloaded. Markdown conversion is additionally skipped — with text and metadata still returned normally — for PDFs over 25MB or 500 pages, since converting very large or image-heavy documents to Markdown is disproportionately slow.

**Why did I get text and metadata but no `markdown`?**
Either `convertToMarkdown` wasn't enabled, or the PDF exceeded the 25MB / 500-page Markdown limit above. Check the run log for a specific message.

**Can I schedule recurring runs?**
Yes. Use [Apify Schedules](https://docs.apify.com/platform/schedules) to re-process a set of PDF URLs on a recurring basis.

**Can I access the data via API?**
Yes. Use the [Apify API](https://docs.apify.com/api/v2) or the official [Python](https://docs.apify.com/api/client/python) and [JavaScript](https://docs.apify.com/api/client/js) client libraries to run the Actor and retrieve results programmatically.

**What export formats are supported?**
JSON, CSV, Excel (XLSX), XML, and HTML. Download directly from the Apify Console or via the API.

**Is there a free trial?**
Yes. New Apify users get free platform credit to try PDF Text Extractor before committing to a paid plan.

**I found an issue or have a feature request.**
Open an issue on the [Issues tab](https://apify.com/parsebird/pdf-text-extractor/issues) or contact ParseBird via the Apify Console.

# Actor input Schema

## `urls` (type: `array`):

Direct URLs to PDF files to extract text and metadata from.

## `includePages` (type: `boolean`):

Include a per-page text breakdown in the output, in addition to the full document text.

## `convertToMarkdown` (type: `boolean`):

Also generate a Markdown version of each PDF (headings, lists, and basic formatting preserved). Adds a separate charge per PDF — see Pricing. Skipped for PDFs over 25MB or 500 pages; text and metadata are still returned for those.

## `maxConcurrency` (type: `integer`):

Maximum number of PDFs to download and process in parallel. Kept modest by default because large PDFs processed in parallel can add up in memory.

## `timeoutPerPdfSecs` (type: `integer`):

Maximum time to wait for each PDF to download before giving up on it.

## Actor input object example

```json
{
  "urls": [
    "https://www.orimi.com/pdf-test.pdf"
  ],
  "includePages": true,
  "convertToMarkdown": false,
  "maxConcurrency": 3,
  "timeoutPerPdfSecs": 60
}
```

# Actor output Schema

## `dataset` (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 = {
    "urls": [
        "https://www.orimi.com/pdf-test.pdf"
    ],
    "maxConcurrency": 3,
    "timeoutPerPdfSecs": 60
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/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 = {
    "urls": ["https://www.orimi.com/pdf-test.pdf"],
    "maxConcurrency": 3,
    "timeoutPerPdfSecs": 60,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/pdf-text-extractor").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 '{
  "urls": [
    "https://www.orimi.com/pdf-test.pdf"
  ],
  "maxConcurrency": 3,
  "timeoutPerPdfSecs": 60
}' |
apify call parsebird/pdf-text-extractor --silent --output-dataset

```

## MCP server setup

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

```

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/HNXEwJkVWBSx6wj9y/builds/1HZReEIH9HOBuL2Q3/openapi.json
