# PDF to Text and Markdown (with OCR for scanned PDFs) (`psypherz/pdf-to-text-markdown`) Actor

Convert PDFs to clean text and Markdown with headings, lists and paragraphs. Scanned pages are read with OCR automatically. Built for RAG, LLM and AI agent pipelines.

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

## Pricing

from $1.50 / 1,000 pages

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 and Markdown (with OCR for scanned PDFs)

Convert PDFs into clean text and Markdown with headings, bullet lists and paragraphs. Most two-column layouts read in the right order, running headers, footers and sideways margin text are removed, and words broken across lines are joined again. Scanned pages are found automatically and read with OCR. Paste PDF links or upload a file. It is built for RAG, LLM and AI agent pipelines, and you need no API key.

**Price: US$0.0015 per page, plus a US$0.001 run fee. Scanned pages cost US$0.003 extra for OCR.** A 50-page report costs US$0.076.

### What people use it for

- **RAG and chatbots:** Markdown keeps headings, so you can split documents by section before embedding.
- **AI agents:** give an agent any PDF link and get text it can read.
- **Research:** pull the text out of reports, papers and filings in bulk.
- **Search indexes:** make a PDF library searchable.
- **Old scans:** OCR turns image-only PDFs into text.

### Example output

Real output from the sample file (IRS Form W-9, 6 pages, public domain). Markdown excerpt:

```markdown
## General Instructions

Section references are to the Internal Revenue Code unless otherwise noted. Future developments. For the latest information about developments related to Form W-9 and its instructions, such as legislation enacted after they were published, go to www.irs.gov/FormW9.

### What’s New

Line 3a has been modified to clarify how a disregarded entity completes this line...
```

| fileName | title | pageCount | pagesProcessed | ocrPages | charCount |
|---|---|---|---|---|---|
| fw9.pdf | Form W-9 (Rev. March 2024) | 6 | 6 | \[] | 37714 |

```json
{
  "sourceUrl": "https://www.irs.gov/pub/irs-pdf/fw9.pdf",
  "fileName": "fw9.pdf",
  "title": "Form W-9 (Rev. March 2024)",
  "pageCount": 6,
  "pagesProcessed": 6,
  "ocrPages": [],
  "charCount": 37714,
  "truncatedInDataset": false,
  "markdownUrl": "https://api.apify.com/v2/key-value-stores/.../records/pdf-001.md",
  "textUrl": "https://api.apify.com/v2/key-value-stores/.../records/pdf-001.txt",
  "text": "Form W-9 ...",
  "markdown": "...# General Instructions\n\nSection references are to...",
  "processedAt": "2026-10-27T09:00:00+00:00"
}
```

`ocrPages` lists the page numbers that were read with OCR. Very long documents are cut at 1.5 million characters in the dataset (`truncatedInDataset: true`). The full text and Markdown are always in the files at `textUrl` and `markdownUrl`.

### Input

| Field | What it does | Default |
|---|---|---|
| `pdfUrls` | Direct links to PDF files, up to 200. 200 MB per file. | 1 sample PDF |
| `uploadedFile` | Or upload one PDF from your computer. | none |
| `ocrMode` | `auto` uses OCR only on pages with no text layer. `always` reads every page with OCR. `never` skips OCR. | `auto` |
| `ocrLanguages` | Up to 4 of 20 languages for OCR, including English, German, French, Spanish, Chinese, Japanese, Arabic and Hindi. | English |
| `maxPagesPerPdf` | Only the first pages up to this number are processed and billed, 1 to 2,000. | `300` |
| `includePages` | Add the text of each page separately, for citations and page-level chunking. | `false` |

### Pricing

| Event | Price |
|---|---|
| Run fee, once per run (per GB of memory; the default is 1 GB) | US$0.001 |
| Page processed | US$0.0015 |
| OCR on a scanned page (added to the page price) | US$0.003 |

Examples: a 1-page PDF costs US$0.0025. A 50-page report costs US$0.076. A 100-page scanned document costs US$0.451. Files that fail are listed with the reason and not charged.

### Limits

- Password-protected PDFs are refused.
- Tables come out as text lines. Their cell structure is not kept.
- Markdown headings are detected from font size. Headings set in bold at body size come out as normal text.
- Pages full of formulas, such as maths papers, can come out with some sentences out of order around the formulas.
- OCR works best on printed text scanned at 200 dpi or more.

### FAQ

**Why Markdown?** LLMs read Markdown well, and headings make it easy to split long documents into meaningful chunks.

**How does it know a page is scanned?** A page with no text layer, or with almost no text and an image, is treated as scanned.

**Is my file stored?** It is processed on the run's temporary disk and deleted. The results are saved in your own Apify storage.

**Can an AI agent call it?** Yes. Pass a PDF link and get text and Markdown back as JSON.

### More tools from the same developer

Same style: clean JSON output, pay only for results, no charge on failed items.

| Tool | What it does |
|---|---|
| [Bulk Keyword Search Volume](https://apify.com/PsypherZ/keyword-search-volume) | Google Ads search volume, CPC, competition and 12-month trend for up to 10,000 keywords |
| [Google Trends API](https://apify.com/PsypherZ/google-trends-api) | Interest over time, by region, and rising queries and topics for up to 500 keywords |
| [Google SERP Results](https://apify.com/PsypherZ/google-serp-results) | Organic results, featured snippets and People Also Ask for any keyword, country and device |
| [Google AI Overview Tracker](https://apify.com/PsypherZ/google-ai-overview-tracker) | Which keywords show an AI Overview, what it says, and whether it cites your site |
| [Audio and Video Transcriber](https://apify.com/PsypherZ/audio-video-transcriber) | Timestamped transcripts from audio and video files in 90+ languages |
| [Subtitle Generator](https://apify.com/PsypherZ/subtitle-generator) | Ready-to-use SRT and WebVTT subtitles from audio and video files |
| [Podcast Transcriber](https://apify.com/PsypherZ/podcast-transcriber) | Timestamped transcripts of podcast episodes from any RSS feed or Apple Podcasts link |
| [Image OCR](https://apify.com/PsypherZ/image-ocr) | Text from images in 20 languages, with confidence scores |
| [Bulk PageSpeed Insights Audit](https://apify.com/PsypherZ/bulk-pagespeed-audit) | Core Web Vitals and Lighthouse scores for many pages, mobile and desktop |

# Actor input Schema

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

Direct links to PDF files. Up to 200 per run, 200 MB each.

## `uploadedFile` (type: `string`):

Upload one PDF from your computer.

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

Auto finds scanned pages and reads them with OCR. OCR pages cost a little more.

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

Languages in the text. Pick up to 4. Fewer languages give better accuracy.

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

Only the first pages up to this number are processed and billed.

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

Add a list with the text of each page, for citations and chunking.

## Actor input object example

```json
{
  "pdfUrls": [
    "https://www.irs.gov/pub/irs-pdf/fw9.pdf"
  ],
  "ocrMode": "auto",
  "ocrLanguages": [
    "eng"
  ],
  "maxPagesPerPdf": 300,
  "includePages": false
}
```

# Actor output Schema

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

One row per PDF: title, page count, OCR pages and links to the Markdown and text files.

# 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://www.irs.gov/pub/irs-pdf/fw9.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("psypherz/pdf-to-text-markdown").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://www.irs.gov/pub/irs-pdf/fw9.pdf"] }

# Run the Actor and wait for it to finish
run = client.actor("psypherz/pdf-to-text-markdown").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 '{
  "pdfUrls": [
    "https://www.irs.gov/pub/irs-pdf/fw9.pdf"
  ]
}' |
apify call psypherz/pdf-to-text-markdown --silent --output-dataset

```

## MCP server setup

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

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/Ady5Lo1j0FErXNumM/builds/XIwanTKaehvuzyCCr/openapi.json
