# PDF to Text & OCR - DOCX, Scanned PDF, Images to Text (`sipki/docs-to-text-ocr`) Actor

Convert PDF, DOCX, PNG, JPG and TIFF files to clean text, page by page. Text-layer PDFs are read directly without OCR; scanned pages and images are OCR'd in 7 languages. Optional Markdown and RAG chunks. $0.003 per document, $0.006 per OCR page, failed files free.

- **URL**: https://apify.com/sipki/docs-to-text-ocr.md
- **Developed by:** [SIPKI LLC](https://apify.com/sipki) (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 $3.00 / 1,000 documents

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 & OCR - DOCX, scanned PDF and images to clean text (RAG-ready)

**Give it links to PDF, DOCX, PNG, JPG or TIFF files; get clean text per page with metadata - $0.003 per document, $0.006 per OCR page, failed files free.**

PDFs that already have a text layer are read directly - **no OCR, no OCR price**. Only scanned pages and images go through OCR (English, German, French, Spanish, Russian, Italian, Portuguese). Optional Markdown and paragraph-aligned chunks with page numbers for search and RAG pipelines.

**Try it now:** press **Start** with the prefilled input (one public NIST PDF). It returns the full text, page by page, for $0.003.

### What you get per document

- `text` - full text; `pages[]` - text per page with `method` (`text-layer` or `ocr`) and OCR confidence
- `pages_count`, `pages_ocr`, `text_layer` (`full` / `partial` / `none`), `language`, `ocr_confidence`, `words`, `title`, `author`
- optional `markdown` (DOCX headings, lists and tables are kept) and `chunks[]` for RAG (about N characters, paragraph-aligned, with `page_start` / `page_end`)
- failed documents come back as `status: "error"` with the reason, and are **free**

### Input

- **URLs** - direct links to files (file type is detected from content)
- **Key-value store keys** - files you uploaded to a store (upload with the real Content-Type)
- **OCR languages** - English, German, French, Spanish, Russian, Italian, Portuguese (English is always included)
- **OCR mode** - `auto` (OCR only pages without text), `force`, `never`
- Markdown, chunk size and overlap, max pages per document, max file size, OCR DPI

### Pricing (pay per event)

- **$0.003 per document** without OCR (PDF with text layer, DOCX)
- **$0.006 per OCR page** (scanned PDF pages and images; the pages of such a document that already have text are not charged)
- No start fee. Failed documents are not charged. Your maximum-charge setting is respected: the actor stops before it would exceed it and never returns unpaid OCR pages.

### Notes and limits

- OCR quality depends on the scan. Tesseract handles clean scans well; low-resolution, skewed or handwritten pages are weaker. Check `ocr_confidence`.
- Password-protected PDFs are reported as failed. Images embedded inside DOCX files are not OCR'd.
- DOCX files have no fixed pages: the text comes back as one page; `pages_count` is filled when the file declares it.
- Only the files you provide are processed; no websites are crawled. A URL is fetched once, as a plain download, with the user agent `SipkiDocsToText/1.0 (+https://apify.com/sipki/docs-to-text-ocr)`. If the host answers 401, 403 or 429, the document is reported as failed (free): no retry, no workaround, no proxy.
- Links to private or internal addresses (private ranges, loopback, link-local, cloud metadata such as `169.254.169.254`) are refused, also after redirects.
- Process only files you have the right to process. Documents you submit may be protected by copyright; you are responsible for that.
- Open-source components: pypdfium2 (Apache-2.0/BSD-3), pdfminer.six (MIT), python-docx (MIT), Pillow (HPND), Tesseract (Apache-2.0).

### How to use

1. Paste direct file links into **URLs**, or upload files to a key-value store and list their keys.
2. Optional: OCR languages, OCR mode (`auto` / `force` / `never`), Markdown, chunk size.
3. Press **Start**. Export as JSON, CSV or Excel, or call it from the Apify API, a schedule, an integration or the Apify MCP server.

### Who uses it

- **Teams building search or RAG** over contracts, reports and manuals.
- **Back-office automation** - read invoices, forms and scanned letters into text.
- **Researchers** - bulk-extract text from public reports.

### More questions

**How much do 100 text PDFs cost?** $0.30. A 10-page scanned PDF costs $0.06 (10 OCR pages).
**Does it read handwriting?** Not reliably. Clean printed scans work best; check `ocr_confidence`.
**Are images inside DOCX files OCR'd?** No, only the document text.

### Not affiliated

Not affiliated with, endorsed or sponsored by NIST, the Tesseract OCR project, or the authors of the open-source components named above. Names are used only to identify them.

### Content rights

You provide the documents and are responsible for having the right to process them and to use the extracted text. The Actor does not check copyright or licences of your files.

### Acceptable use

This Actor is a tool. You decide which sites, companies or files it processes and what you do with the results, and you are responsible for that use. Use it only where you have the right to access the data, and in line with applicable law (including data-protection, anti-spam and copyright law) and the terms of the sources. Do not use it to send unsolicited messages, to build lists for spam, to bypass blocks or access controls, or to place excessive load on any site. If a site owner asks us to stop, we may exclude that site. Sipki, LLC does not receive or store your results; they stay in your Apify storage.

### No warranty

The Actor and its output are provided "as is", without warranty of accuracy, completeness or fitness for a purpose. OCR output can contain errors. Verify results before relying on them. Liability of Sipki, LLC is limited as set out in the Apify Standard Actor Contract that governs your use of this Actor.

### Personal data

Your files and the extracted text may contain personal data (for example names, ID numbers, medical or financial details in scans). For such data you are the controller and Sipki, LLC acts only as your processor under section 5 of the Apify Standard Actor Contract. Files and extracted text are processed only to produce your dataset; the Actor stores nothing outside your run's storages, and the creator does not access run data except on your support request. You need a lawful basis for your processing and must handle data-subject requests. To request deletion of anything related to you, open an Issue on this Actor's page.

### For site owners (opt-out)

When you give the Actor a link, it downloads that single file with the user agent `SipkiDocsToText/1.0 (+https://apify.com/sipki/docs-to-text-ocr)`. It does not crawl and does not read robots.txt, because it only fetches links that a user supplies. To have your domain excluded, or to report a problem, open an Issue on this Actor's page: your domain will be added to the block list within 3 business days, and every run checks that list.

# Actor input Schema

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

Direct links to PDF, DOCX, PNG, JPG, TIFF, BMP, GIF or WEBP files (http/https), one per line. The file type is detected from the content, not the extension.

## `keyValueStoreKeys` (type: `array`):

Keys of files you uploaded to a key-value store (upload each file with its real Content-Type, e.g. application/pdf). Combine with 'URLs' freely.

## `keyValueStoreName` (type: `string`):

Name of the store that holds the keys above. Leave empty to use this run's default store.

## `inlineFiles` (type: `object`):

Small files passed directly in the input as {"name.pdf": "<base64>"}. Total input size is limited by Apify (about 9 MB); use URLs or a key-value store for anything bigger.

## `languages` (type: `array`):

Languages of scanned pages and images. English is always added. Choose every language that occurs in your documents; each extra language slightly slows OCR.

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

auto: OCR only pages that have no text layer (default, cheapest). force: OCR every page (use when a PDF has a broken or garbage text layer). never: text layers only, no OCR.

## `outputMarkdown` (type: `boolean`):

Add a 'markdown' field. DOCX headings, lists and tables are preserved; PDF and OCR text becomes paragraphs with page markers.

## `chunkSize` (type: `integer`):

0 = no chunks. Otherwise adds a 'chunks' array of about this many characters, cut on paragraph boundaries, each with its page range.

## `chunkOverlap` (type: `integer`):

How much of the previous chunk is repeated at the start of the next one (paragraph granularity).

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

Pages after this number are not processed (and not charged). The output tells you when a document was truncated.

## `maxDocuments` (type: `integer`):

Stop after this many documents (the rest are skipped).

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

Larger files are reported as failed (free).

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

Resolution used to rasterize PDF pages before OCR. 300 is the best default; 200 is faster and fine for clean scans.

## `pageSegmentationMode` (type: `integer`):

3 = fully automatic (default), 4 = single column, 6 = single uniform block, 11 = sparse text.

## Actor input object example

```json
{
  "urls": [
    "https://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf"
  ],
  "languages": [
    "eng"
  ],
  "ocrMode": "auto",
  "outputMarkdown": false,
  "chunkSize": 0,
  "chunkOverlap": 100,
  "maxPagesPerDocument": 200,
  "maxDocuments": 1000,
  "maxFileSizeMb": 50,
  "ocrDpi": 300,
  "pageSegmentationMode": 3
}
```

# Actor output Schema

## `results` (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://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("sipki/docs-to-text-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://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf"] }

# Run the Actor and wait for it to finish
run = client.actor("sipki/docs-to-text-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://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf"
  ]
}' |
apify call sipki/docs-to-text-ocr --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sipki/docs-to-text-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/wQftSeialza431Bbn/builds/Undij2TGHgwgPOPlf/openapi.json
