# PDF to Text & Markdown Converter with OCR (DOCX, Images) (`poised_beardlichen/pdf-to-text-markdown-ocr`) Actor

Use this when you need text or LLM-ready Markdown from a PDF, DOCX or image URL, incl. scanned pages (OCR, 27 languages). $0.003/document + $0.0003/text page (first 30) or $0.005/OCR page. Input: {"url":"https://arxiv.org/pdf/1706.03762"}. Output: markdown, text, pageCount, ocrPages, metadata.

- **URL**: https://apify.com/poised_beardlichen/pdf-to-text-markdown-ocr.md
- **Developed by:** [Isaac](https://apify.com/poised_beardlichen) (community)
- **Categories:** AI, Agents, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

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 to Text & Markdown Converter with OCR

**Convert PDFs, Word documents (DOCX) and images into clean plain text and LLM-ready Markdown, in bulk, with automatic OCR for scanned pages.** Paste a list of document URLs and get back one tidy result per document (or per page): full text, Markdown with headings and lists, page counts, OCR stats and document metadata. Built for **RAG pipelines, vector databases, AI agents, search indexing, data extraction and archiving**.

- 📄 **PDF to text and PDF to Markdown**: keeps reading order on **multi-column** layouts (research papers, reports, newsletters)
- 🔍 **Automatic OCR** of scanned or image-only pages, and of pages whose fonts produce garbled text. **27 OCR languages**
- 📝 **DOCX to Markdown** (Word) and **image to text** (PNG, JPEG, TIFF incl. multi-page, WebP, BMP, GIF)
- 🧩 **One result per page** option, so you can chunk and cite page numbers in RAG
- 🧹 Strips repeating headers, footers and page numbers; joins hyphenated words; turns dot leaders into clean tables of contents
- 🏷️ Metadata: title, author, subject, keywords, creator, producer, creation/modification dates, PDF version, page size, encryption
- 🔗 Works with direct links, **Google Drive** and **Dropbox** share links. Handles redirects, slow servers and retries
- 💸 **Pay only for what converts.** Broken links, web pages, unsupported or oversized files cost nothing. No monthly fee, no start fee

### What can I use it for?

- **Feed documents to ChatGPT, Claude, LangChain, LlamaIndex or a vector database.** Markdown output keeps structure, which makes embeddings and answers better than raw text.
- **Digitise scanned archives**, such as old contracts, government releases, invoices, forms and books, into searchable text.
- **Monitor and index reports**, like annual reports, central-bank statements, tenders and research papers, alongside a scraper.
- **Bulk-extract text** from thousands of PDFs found by another Apify Actor (pass its dataset URLs straight in).

### How to use it

1. Add one or more document URLs to **Document URLs** (the form is prefilled with a working example).
2. Pick **Markdown + plain text**, **Markdown only** or **Plain text only**.
3. Leave **OCR = Auto** (recommended). Pages that already contain text are read directly; only scanned pages are OCRed.
4. Click **Start**. Results appear in the **Output** tab, and you can export them as JSON, CSV, Excel or HTML, or read them through the API.

#### Input example

```json
{
  "urls": [
    "https://arxiv.org/pdf/1706.03762",
    "https://github.com/tesseract-ocr/test/raw/main/testing/phototest.tif"
  ],
  "outputFormat": "both",
  "outputMode": "document",
  "ocrMode": "auto",
  "ocrLanguages": ["eng"]
}
```

#### Output example (one document)

```json
{
  "url": "https://arxiv.org/pdf/1706.03762",
  "success": true,
  "fileType": "pdf",
  "pageCount": 15,
  "textPages": 15,
  "ocrPages": 0,
  "words": 6280,
  "markdown": "### Attention Is All You Need\n\nAshish Vaswani ...\n\n#### Abstract\n\nThe dominant sequence transduction models ...",
  "text": "Attention Is All You Need\n\nAshish Vaswani ...",
  "metadata": { "title": null, "producer": "pdfTeX-1.40.25", "pdfVersion": "1.5", "encrypted": false, "pageFormat": "letter" },
  "durationMs": 312
}
```

In **page mode** you get one item per page with `page`, `ocr`, `ocrConfidence`, `text` and `markdown`. Turn on **Also save .md / .txt files** to get downloadable files in the key-value store. Very large documents are always saved as files, and their dataset text is shortened.

### Pricing

Pay-per-event, no subscription and no start fee:

| Event | Price |
|---|---|
| Document converted | $0.003 |
| Text page (from the PDF's own text layer, or per Word page), **first 30 text pages per document only** | $0.0003 |
| OCR page (scanned page or image that produced text) | $0.005 |

**Long digital documents are capped.** You pay for at most 30 text pages per document, so a 500-page book costs the same as a 30-page report.

**Examples:**

- 10-page digital PDF: **$0.006**
- 10-page scanned PDF: **$0.053**
- 500-page digital PDF: **$0.012**
- 1,000 single-page receipt photos: **$8.00**

#### How does the price compare?

Totals calculated from each Actor's public Apify Store pricing (free-tier prices, checked 19 October 2026):

| Actor | 10-page digital PDF | 10-page scanned PDF |
|---|---|---|
| **This Actor** | **$0.006** | **$0.053** |
| amanatools/pdf-ocr-extractor | $0.017 | $0.157 |
| ely_source/pdf-ocr | OCR only | $0.21 |
| nerolabs/bulk-ocr-image-pdf-to-text | OCR only | $0.05 |
| nidamindllc/doc-ocr | OCR only | $0.04 |

This Actor handles digital PDFs, scans, DOCX and images in one run, and digital pages are capped at 30 per document.

Blank pages are not charged as OCR pages, and failed documents are free. Set **Maximum cost per run** in Apify and the Actor stops cleanly at your limit. It never runs over.

### Tips for best results

- Use **OCR languages** that match the document. 1–3 languages give the best speed and accuracy.
- Raise **OCR resolution** to 300 DPI for tiny print, or lower it to 150 for large, clean scans.
- Use **Max pages per document** to sample huge files cheaply.
- Use **OCR = Never** for pure digital PDFs when you want the lowest price and the fastest speed.

### FAQ

**Does it work on scanned PDFs?** Yes. Auto mode detects pages without a usable text layer and runs Tesseract 5 (LSTM) OCR on them. It also catches PDFs whose embedded fonts produce garbage characters.

**Can it read tables?** Table text is extracted in reading order, but it is not rebuilt as Markdown tables.

**Password-protected PDFs?** PDFs that open without a password (owner-password restrictions only) work. PDFs that need a password to open are reported as errors and are not charged.

**Is my data stored?** Files are downloaded into the run's temporary container and deleted after conversion. Results live only in your own Apify storage.

**Can AI agents use it?** Yes. It runs with limited permissions and simple pay-per-event pricing, and it works from the Apify API, MCP server and integrations (Make, Zapier, n8n, LangChain).

**How much does a huge PDF cost?** Text pages are capped at 30 per document, so a 500-page digital PDF costs $0.012 in total. OCR pages are always charged per page, because each one needs real compute.

**What file size is supported?** Up to 500 MB per file (default limit 100 MB), with thousands of pages per document.

**Which languages can OCR read?** English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Swedish, Danish, Norwegian, Finnish, Czech, Turkish, Russian, Ukrainian, Greek, Arabic, Hebrew, Hindi, Vietnamese, Indonesian, Thai, Chinese (Simplified and Traditional), Japanese and Korean.

### Use it from the API

**Python**

```python
from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("poised_beardlichen/pdf-to-text-markdown-ocr").call(
    run_input={"urls": ["https://arxiv.org/pdf/1706.03762"]})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["markdown"][:500])
```

**cURL** (waits for the run and returns the results)

```bash
curl -X POST "https://api.apify.com/v2/acts/poised_beardlichen~pdf-to-text-markdown-ocr/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://arxiv.org/pdf/1706.03762"]}'
```

### Use with AI agents and RAG (MCP)

Give Claude, Cursor or any MCP client the ability to read PDFs through the [Apify MCP server](https://mcp.apify.com):

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com/?tools=poised_beardlichen/pdf-to-text-markdown-ocr",
      "headers": { "Authorization": "Bearer <YOUR_APIFY_TOKEN>" }
    }
  }
}
```

For **RAG**, turn on page mode. Each page becomes its own item with a page number, ready to chunk, embed and cite. It also works with LangChain's `ApifyWrapper`, LlamaIndex, Make, Zapier and n8n.

### Calling it from an AI agent or a script (async pattern)

A single text PDF usually finishes in under 30 seconds. Long scanned PDFs (OCR) take longer, roughly 1–3 seconds per page. The Apify MCP server waits only about 30–45 seconds for a run before it returns. So for batches, slow pages, or whenever a call returns before the run is done, start the run and fetch the results afterwards rather than waiting on it:

1. **Start the run:** `POST https://api.apify.com/v2/acts/poised_beardlichen~pdf-to-text-markdown-ocr/runs` with input such as `{"url": "https://arxiv.org/pdf/1706.03762"}`. The response contains `data.id` (the run ID) and `data.defaultDatasetId`.
2. **Wait for it to finish:** poll `GET https://api.apify.com/v2/actor-runs/<runId>?waitForFinish=60` until `status` is `SUCCEEDED`.
3. **Fetch the results:** `GET https://api.apify.com/v2/datasets/<defaultDatasetId>/items?clean=true`.

Send your token as `Authorization: Bearer <APIFY_TOKEN>`. Through MCP, if the call returns a run ID instead of results, use the server's run-status and dataset tools (e.g. `get-actor-run`, then `get-dataset-items`) with that ID. For small, quick jobs you can use the synchronous endpoint `POST /v2/acts/poised_beardlichen~pdf-to-text-markdown-ocr/run-sync-get-dataset-items` instead, which waits for up to 300 seconds.

### Other tools by us

- [Website Screenshot & PDF API](https://apify.com/poised_beardlichen/website-screenshot-pdf): turn any web page into a PDF or screenshot with cookie banners removed, then convert that PDF to text here.
- [Bulk Email Verifier & Validator](https://apify.com/poised_beardlichen/email-verifier-bulk): check email lists for valid syntax, MX records, disposable and role addresses and typos, at $0.30 per 1,000 emails.
- [Image to Text OCR API](https://apify.com/poised_beardlichen/image-to-text-ocr): extract text from PNG, JPEG, TIFF and WebP images in 27 languages, at $1.50 per 1,000 images.
- [Bulk PageSpeed & Lighthouse Checker](https://apify.com/poised_beardlichen/pagespeed-lighthouse-checker): Lighthouse scores, Core Web Vitals and top fixes for many URLs on mobile and desktop, from $0.005 per audit.
- [Website Screenshot & PDF for AI Agents](https://apify.com/poised_beardlichen/website-screenshot-pdf-agent): a lightweight copy of the screenshot tool for agents and one-off calls (no Standby). Same prices, starting at $0.0015 per screenshot.

### Support

Found a document that doesn't convert well? Open an issue on the Actor's **Issues** tab with the URL. We usually fix problems within a few days.

# Actor input Schema

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

Shortcut for one document URL, e.g. "https://arxiv.org/pdf/1706.03762". Combined with the list below; provide at least one of the two.

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

Direct links to PDF, DOCX or image files (PNG, JPEG, TIFF, WebP, BMP, GIF). Public Google Drive and Dropbox share links are converted automatically. Add as many as you like - they are processed in parallel. Use "url" instead for a single item.

## `outputFormat` (type: `string`):

Markdown keeps headings, lists and paragraphs (ideal for LLMs, RAG and vector databases). Plain text keeps the original line breaks.

## `outputMode` (type: `string`):

Return one dataset item per document, or one item per page with its page number.

## `ocrMode` (type: `string`):

Auto detects scanned or image-only pages (and pages with broken/garbled fonts) and runs OCR only on those. Images are always OCRed.

## `ocrLanguages` (type: `array`):

Language(s) of scanned text. Pick 1-3 for best accuracy and speed; English is used if empty.

## `ocrDpi` (type: `integer`):

Render resolution for OCR. 200 is the best balance; use 300 for tiny print, 150 for large, clean scans.

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

Stop after this many pages of each document (0 = all pages). Useful to cap cost on huge files.

## `startPage` (type: `integer`):

First page to extract (PDF only).

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

In document mode, also add a 'pages' array with the text/markdown of every page.

## `pageMarkers` (type: `boolean`):

Insert  comments into the Markdown so you can cite page numbers.

## `removeHeadersFooters` (type: `boolean`):

Drop running heads, footers and page numbers that repeat on most pages.

## `saveFiles` (type: `boolean`):

Store each document's Markdown and text as files in the key-value store and return download links. Very large documents are always saved as files.

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

Larger files are skipped (not charged).

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

How many documents to download and convert at the same time.

## Actor input object example

```json
{
  "urls": [
    "https://arxiv.org/pdf/1706.03762",
    "https://github.com/tesseract-ocr/test/raw/main/testing/phototest.tif"
  ],
  "outputFormat": "both",
  "outputMode": "document",
  "ocrMode": "auto",
  "ocrLanguages": [
    "eng"
  ],
  "ocrDpi": 200,
  "maxPagesPerDocument": 0,
  "startPage": 1,
  "includePages": false,
  "pageMarkers": false,
  "removeHeadersFooters": true,
  "saveFiles": false,
  "maxFileSizeMb": 100,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

Dataset items: url, success, fileType, pageCount, textPages, ocrPages, text, markdown, metadata, error.

## `files` (type: `string`):

Per-document .md and .txt files (when 'Also save files' is on, or the document is very large).

# 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://arxiv.org/pdf/1706.03762",
        "https://github.com/tesseract-ocr/test/raw/main/testing/phototest.tif"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("poised_beardlichen/pdf-to-text-markdown-ocr").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://arxiv.org/pdf/1706.03762",
        "https://github.com/tesseract-ocr/test/raw/main/testing/phototest.tif",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("poised_beardlichen/pdf-to-text-markdown-ocr").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://arxiv.org/pdf/1706.03762",
    "https://github.com/tesseract-ocr/test/raw/main/testing/phototest.tif"
  ]
}' |
apify call poised_beardlichen/pdf-to-text-markdown-ocr --silent --output-dataset

```

## MCP server setup

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

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/rzWYaAczxhbWVXTQJ/builds/PdwDQFTYkfEQoaiX6/openapi.json
