# Document OCR | PDF to Markdown | Invoice, Table & Image to Text (`nidamindllc/doc-ocr`) Actor

Document OCR and PDF to Markdown. Extract text, tables and structured data from PDFs and images with state-of-the-art PaddleOCR-VL. Handles invoices, receipts, forms and scanned documents in 100+ languages, returning LLM-ready Markdown plus layout blocks for RAG. Pay per page.

- **URL**: https://apify.com/nidamindllc/doc-ocr.md
- **Developed by:** [Scott Shinn](https://apify.com/nidamindllc) (community)
- **Categories:** AI, Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 page ocr'ds

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

## Document OCR API — PDF & Image to Markdown (PaddleOCR-VL)

Give this Actor a list of image or PDF URLs. Get back clean **Markdown** and structured **layout blocks** — tables kept as tables, headings kept as headings, reading order preserved — ready to drop into a RAG pipeline, a search index, or a data-extraction step. Runs on GPU with [PaddleOCR-VL](https://github.com/PaddlePaddle/PaddleOCR), across 100+ languages.

### See it work

**Input:**

```json
{ "imageUrls": ["https://templates.invoicehome.com/invoice-template-us-neat-750px.png"] }
```

**Output** (one dataset item — trimmed):

```markdown
### INVOICE

East Repair Inc.
1912 Harvest Lane
New York, NY 12210

INVOICE #  US-001
INVOICE DATE  11/02/2019
DUE DATE  26/02/2019
```

…and the invoice's line-item table comes back as a real table, not flattened text:

| QTY | DESCRIPTION | UNIT PRICE | AMOUNT |
|-----|-------------|-----------|--------|
| 1 | Front and rear brake cables | 100.00 | 100.00 |
| 2 | New set of pedal arms | 15.00 | 30.00 |
| 3 | Labor 3hrs | 5.00 | 15.00 |

Every page also returns `blocks` — the layout regions with their type and bounding-box coordinates — if you want to post-process programmatically.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `imageUrls` | array of strings | **Required.** Publicly accessible image or PDF URLs. Each PDF is OCR'd page by page. |
| `maxPages` | integer | Optional. Cap pages per PDF (`0` = no cap). |

### Output

One dataset item per URL:

```json
{
  "url": "...",
  "ok": true,
  "numPages": 1,
  "markdown": "## INVOICE\n\nEast Repair Inc. ...",
  "pages": [{ "markdown": "...", "blocks": [ /* type + bbox per region */ ] }]
}
```

A URL that fails comes back as `{ "url": "...", "ok": false, "error": "..." }`, so one bad link never kills the run.

### What it's good at

- **Tables and forms** — invoices, receipts, financial statements come back with rows and columns intact.
- **Scanned documents and photos** — printed text is the sweet spot; handwriting and degraded scans work with lower confidence.
- **Multi-column and math-heavy pages** — research papers, books, reports keep their reading order and formulas.
- **100+ languages** — Latin, Cyrillic, Arabic, Devanagari, CJK, Thai, and more.

The engine is PaddleOCR-VL-1.6, which sits at the top of the [OmniDocBench](https://github.com/opendatalab/OmniDocBench) document-parsing benchmark — ahead of general-purpose vision models many times its size.

### How it compares

| Tool | Output | Trade-off |
|------|--------|-----------|
| **This Actor** | Markdown + layout blocks | Top OmniDocBench accuracy; pages run one at a time |
| Tesseract actors | Plain text | Faster, weaker on tables and complex layout |
| Google Vision / AWS Textract | Text + basic layout | Robust, but per-call pricing and less LLM-ready output |

### Pricing

Pay per page OCR'd — one image is one page, a 10-page PDF is ten. No subscription, no minimum.

### Notes

- URLs must be publicly reachable.
- Pages run one at a time through a single warm GPU model, so large batches proceed at a steady rate.

# Actor input Schema

## `imageUrls` (type: `array`):

List of publicly accessible image or PDF URLs to OCR. Each PDF is rendered page-by-page.

## `maxPages` (type: `integer`):

Cap on how many pages to OCR from each PDF (0 = service default).

## Actor input object example

```json
{
  "imageUrls": [
    "https://tesseract.projectnaptha.com/img/eng_bw.png"
  ],
  "maxPages": 0
}
```

# Actor output Schema

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

Markdown text, number of pages, and layout blocks for every URL processed.

# 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 = {
    "imageUrls": [
        "https://tesseract.projectnaptha.com/img/eng_bw.png"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("nidamindllc/doc-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 = { "imageUrls": ["https://tesseract.projectnaptha.com/img/eng_bw.png"] }

# Run the Actor and wait for it to finish
run = client.actor("nidamindllc/doc-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 '{
  "imageUrls": [
    "https://tesseract.projectnaptha.com/img/eng_bw.png"
  ]
}' |
apify call nidamindllc/doc-ocr --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nidamindllc/doc-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/ARK3lVdXNvzD8PBUV/builds/qQ1zTZCkvbtQXCUeD/openapi.json
