# Document Parser — PDF/DOCX to Markdown & JSON for RAG (`genuine_qa/document-parser`) Actor

Convert PDF, DOCX, PPTX, XLSX, HTML and images into clean Markdown or JSON for RAG and LLM pipelines. Powered by IBM's open-source Docling.

- **URL**: https://apify.com/genuine_qa/document-parser.md
- **Developed by:** [Rahul Bhiwagade](https://apify.com/genuine_qa) (community)
- **Categories:** Agents, Automation
- **Features:** Limited permissions
- **Stats:** 10 total users, 1 monthly users, 96.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00001 / actor start

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Document Parser — PDF, DOCX & more → Markdown / JSON for RAG & LLMs

Turn messy documents into clean, structured **Markdown** or **JSON** that's ready
to drop straight into RAG pipelines, vector databases, and LLM prompts.

Send one or more document URLs and get back well-structured content with
**headings, lists, reading order, and real tables preserved** — powered by
state-of-the-art open-source document-AI models for layout analysis and table
structure recognition.

No local setup, no GPU, no model wrangling. Just URLs in, clean text out.

***

### ✨ Why use this

- **Built for RAG / LLMs** — Markdown output drops cleanly into prompts and chunkers; JSON output gives you structured elements for custom pipelines.
- **Real table extraction** — tables come back as proper Markdown tables (rows/columns intact), not jumbled text.
- **Layout-aware** — detects headings, lists, captions, and correct reading order across multi-column pages.
- **Many formats, one Actor** — PDF, Word, PowerPoint, Excel, HTML, and images.
- **Robust** — each document is processed independently; one bad URL never fails the whole run, and errors come back with a clear, human-readable reason.
- **Optional OCR** — extract text from scanned or image-only PDFs.

### 📄 Supported formats

| Type | Extensions |
|---|---|
| PDF | `.pdf` |
| Word | `.docx` |
| PowerPoint | `.pptx` |
| Excel | `.xlsx` |
| Web / markup | `.html`, `.md` |
| Images | `.png`, `.jpg`, `.tiff` (with OCR) |

### 💡 Common use cases

- **RAG ingestion** — convert a library of PDFs/Docs into Markdown for chunking and embedding.
- **Knowledge bases & search** — extract clean, structured text from reports, manuals, and contracts.
- **LLM context** — feed papers, datasheets, or filings to a model without copy-paste noise.
- **Dataset building** — turn document collections into structured JSON for training or analysis.
- **Table harvesting** — pull tables out of financial reports or research papers as usable Markdown.

***

### 🚀 How to use

#### From the Apify Console

1. Click **Try for free / Start**.
2. Paste one or more **Document URLs** (direct links to the files).
3. Pick an **Output format** — `markdown`, `json`, or `both`.
4. (Optional) Turn on **OCR** for scanned/image PDFs.
5. Click **Start** and grab the results from the **Dataset** tab (export as JSON, CSV, Excel, or via API).

#### Input

| Field | Type | Required | Description |
|---|---|:---:|---|
| `documentUrls` | array of strings | ✅ | Direct URLs to the documents to convert. |
| `outputFormat` | `markdown` | `json` | `both` | | Output format. Default: `markdown`. |
| `doOcr` | boolean | | Run OCR on scanned/image PDFs (slower). Default: `false`. |

**Example input**

```json
{
  "documentUrls": [
    "https://arxiv.org/pdf/2408.09869",
    "https://www.example.com/report.pdf"
  ],
  "outputFormat": "both",
  "doOcr": false
}
```

#### Output

One dataset item per document:

```json
{
  "url": "https://arxiv.org/pdf/2408.09869",
  "status": "success",
  "markdown": "## Abstract\n\nThis technical report introduces ...",
  "json": { "schema_name": "DoclingDocument", "texts": [ ... ], "tables": [ ... ] }
}
```

If a document can't be processed, you get a clear error instead of a crash:

```json
{
  "url": "https://example.com/locked.pdf",
  "status": "error",
  "error": "Download failed with HTTP 403. The URL may be private, expired, or protected (e.g. Cloudflare/login). Provide a direct, publicly accessible document link."
}
```

***

### 🔌 Use the results via API

Run the Actor and read its output from your own code with the
[Apify API client](https://docs.apify.com/api/client/python/):

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")

run = client.actor("genuine_qa/document-parser").call(run_input={
    "documentUrls": ["https://arxiv.org/pdf/2408.09869"],
    "outputFormat": "markdown",
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["status"] == "success":
        print(item["markdown"])
    else:
        print("Failed:", item["url"], "->", item["error"])
```

You can also export results directly as JSON/CSV/Excel from the dataset's
**Export** button, or pull them from the
[Dataset API](https://docs.apify.com/api/v2#/reference/datasets).

***

### ⚙️ Tips & performance

- **Memory:** the conversion models need room — run with **4 GB+** memory for reliable results, more for large or OCR-heavy documents.
- **First page is slowest:** models load once per run, so converting many documents in a single run is more efficient than one run per document.
- **OCR is heavier:** only enable `doOcr` when documents are scanned or image-based — it's significantly slower than parsing digital text.
- **Use direct links:** point to the actual file URL. Pages behind logins, paywalls, or anti-bot challenges (e.g. Cloudflare) can't be downloaded and will return a clear error.

### ❓ FAQ

**Does it handle scanned PDFs?**
Yes — enable `doOcr`. For digital (text-based) PDFs, leave it off for much faster, higher-fidelity results.

**Are tables preserved?**
Yes. Tables are reconstructed and emitted as Markdown tables, and as structured cells in the JSON output.

**Can I process many documents at once?**
Yes — pass multiple URLs in `documentUrls`. Each becomes its own dataset item.

**What happens if one URL is bad?**
That single document is marked `"status": "error"` with a readable message; the rest of the run continues normally.

**Do my documents leave the run?**
The Actor downloads each URL you provide, converts it inside the run, and writes the result to your dataset. It doesn't send your documents anywhere else.

# Actor input Schema

## `documentUrls` (type: `array`):

Direct URLs to documents to convert. Supports PDF, DOCX, PPTX, XLSX, HTML, Markdown and images.

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

Format of the converted output stored in the dataset.

## `doOcr` (type: `boolean`):

Run OCR to read text from scanned or image-based PDFs. Slower and more resource-intensive.

## Actor input object example

```json
{
  "documentUrls": [
    "https://arxiv.org/pdf/2408.09869"
  ],
  "outputFormat": "markdown",
  "doOcr": false
}
```

# 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 = {
    "documentUrls": [
        "https://arxiv.org/pdf/2408.09869"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("genuine_qa/document-parser").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 = { "documentUrls": ["https://arxiv.org/pdf/2408.09869"] }

# Run the Actor and wait for it to finish
run = client.actor("genuine_qa/document-parser").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 '{
  "documentUrls": [
    "https://arxiv.org/pdf/2408.09869"
  ]
}' |
apify call genuine_qa/document-parser --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,genuine_qa/document-parser"
        }
    }
}
```

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/JVysk3zQxpABX0hGH/builds/HTfdPM2GqGH9oB88L/openapi.json
