Word, Excel, PowerPoint & HTML to RAG Chunks (JSON, OCR) avatar

Word, Excel, PowerPoint & HTML to RAG Chunks (JSON, OCR)

Pricing

from $2.10 / 1,000 document unit processeds

Go to Apify Store
Word, Excel, PowerPoint & HTML to RAG Chunks (JSON, OCR)

Word, Excel, PowerPoint & HTML to RAG Chunks (JSON, OCR)

Use to convert a Word document to text for an LLM, extract text from Excel and PowerPoint files, or read text from an image with OCR (also CSV and HTML), with RAG chunks and citations. Input: fileUrls. $0.003 per unit, +$0.01 per OCR image. Not for PDFs or old .doc/.xls files.

Pricing

from $2.10 / 1,000 document unit processeds

Rating

0.0

(0)

Developer

Small Hours

Small Hours

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Security

Limited permissions

Share

Four libraries, four output shapes, and not one of them can tell you which slide the answer came from.

For AI agents choosing a tool

  • Use when: you have URLs of Word (.docx), PowerPoint (.pptx), Excel (.xlsx), CSV or HTML files, or images (PNG, JPG, TIFF, WebP, BMP, GIF), and need text, Markdown, tables and RAG chunks that cite a part, slide or sheet rows.
  • Do not use when: the file is a PDF (use pdf-to-json-tables), audio or video (use transcribe-to-json-chunks), a legacy .doc, .xls, .ppt or .rtf file, or password-protected. Images embedded inside Office files are not OCR'd.
  • Input: {"fileUrls": ["https://example.com/policy.docx"]}. Optional: chunkSize, chunkOverlap, ocrLanguage, maxFileSizeMb, maxUnitsPerFile.
  • Output: one item per file: sourceUrl, documentId, fileName, fileType, unitCount, unitsProcessed, text, markdown, tables, chunks (chunkIndex, page = unit number, charStart, charEnd, text, citation with a label such as part 2, slide 4 or Sheet1 rows 1-500), ocrUsed, warnings.
  • Price per event: $0.003 per unit (unit-processed: about 3,000 characters of Word or HTML text, one slide, or 500 spreadsheet rows) plus $0.01 per OCR'd image (ocr-image); Store discounts apply on Bronze, Silver and Gold. Never charged: failed, empty, corrupt, password-protected, unsupported or over-limit files.
  • Agent payments: limited permissions, pay per event only, no Standby mode, so it is eligible for Apify's agentic payments.

Real output from a platform run on 2026-10-25, a small Word policy file, one chunk, text shortened:

{
"chunkIndex": 0,
"page": 1,
"charStart": 0,
"charEnd": 1195,
"text": "Remote Work Policy\n\n1. Purpose\n\nThis policy explains how employees of Example Widgets Inc. may work from home. It applies to all full-time staff. ...",
"citation": { "type": "page", "page": 1, "label": "part 1" }
}

The citation.label follows the file type, so the reference reads the way a person would say it: part 2 in a Word document, slide 4 in a deck, Sheet1 rows 1-500 in a spreadsheet, frame 2 in a multi-page TIFF. It is the same citation object pdf-to-json-tables puts on a page and transcribe-to-json-chunks puts on a minute, so one pipeline takes all three.

The file type is read from the file's contents, not from its extension, so a signed URL with no extension or the wrong one still works. That is the normal case when files come out of a CMS.

$0.003 per unit, about 3,000 characters of Word or HTML text, one slide, or 500 spreadsheet rows, plus $0.01 per image read with OCR. Files that fail to download, unsupported, legacy, password-protected, corrupt and empty files, anything over your size limit, and units with no text and no table are never charged.

Give it links to Word (.docx), PowerPoint (.pptx), Excel (.xlsx), CSV or HTML files, or images (PNG, JPG, TIFF, WebP, BMP, GIF), and get one clean JSON object per file: plain text, Markdown, every table as rows of strings, and RAG-ready chunks with a citation that says exactly where each chunk came from (slide 4, Sales rows 501-1000, part 2, frame 2). Images are read with OCR.

The chunk format is the same as PDF to JSON (pdf-to-json-tables) and Audio & Video Transcription to JSON (transcribe-to-json-chunks): same chunk format, so one pipeline ingests reports, recordings and Office files.

What it does

  • DOCX to JSON: paragraphs, headings (as Markdown #), lists and tables, in reading order.
  • PPTX to JSON: the text and tables of every slide, plus the speaker notes.
  • XLSX and CSV to JSON: every sheet's rows as arrays of strings in tables, and as tab-separated text for search.
  • HTML to text: headings, paragraphs, lists and tables; scripts, styles and navigation code are dropped. External images, scripts and links in the page are never fetched.
  • Image OCR: PNG, JPG, WebP, BMP and GIF images, and every frame of a multi-page TIFF (scanned faxes), read with Tesseract.
  • Chunks for RAG: text split at sentence or word boundaries (never mid-word), 1,200 characters by default with 150 characters of overlap, each with a citation.
  • Type detection from the content, not the link: links without an extension, or with the wrong one, work.

Who it is for

  • Teams building a company knowledge base or an internal chatbot from policies, meeting notes, slide decks and spreadsheets.
  • Developers of RAG and AI agent pipelines who want one tool and one format for every office file.
  • Analysts who need Excel price lists, budgets or CSV exports as JSON rows.
  • Anyone who needs OCR on screenshots, scanned receipts or faxes without running Tesseract themselves.

Quick start

  1. Open the Actor in Apify Console and press Start. The prefilled input reads two small sample files (a Word policy and a screenshot).
  2. Replace the links with your own: {"fileUrls": ["https://example.com/policy.docx"]}. Each link must point at the file itself (Word, PowerPoint, Excel, CSV, HTML or an image), not at a web page that shows it.
  3. Read the results from the default dataset (JSON, CSV or Excel) or the API: https://api.apify.com/v2/datasets/<datasetId>/items. The SUMMARY record in the key-value store lists every file's status and what was charged.

Input example

{
"fileUrls": [
"https://example.com/handbook.docx",
"https://example.com/q3-review.pptx",
"https://example.com/prices.xlsx"
],
"chunkSize": 1200,
"chunkOverlap": 150
}
FieldTypeDefaultMeaning
fileUrlsarray of stringsone sample .docxPublic http(s) links to the files, up to 100 per run
chunkSizeinteger1200Chunk size in characters, 0 turns chunks off
chunkOverlapinteger150Characters shared by consecutive chunks of the same unit
ocrauto or offautoauto reads images with OCR; off skips images with a free error
ocrLanguageengengOnly English is installed
maxFileSizeMbinteger 1 to 20050Larger files are refused (free) as soon as the size passes the limit
maxUnitsPerFileinteger 1 to 1000200Files with more units return a free too_many_units error

Output format

One dataset item per file:

FieldMeaning
sourceUrlThe link you gave
documentIdsha1 of the link, stable across runs
fileNameLast part of the link
fileTypedocx, pptx, xlsx, csv, html or image, detected from the content
unitCountUnits in the file (see the next table)
unitsProcessedUnits returned (lower only if the run hit its maximum total charge)
textPlain text of all units, separated by a form feed (\f)
markdownMarkdown with headings, lists and tables
tables{tableIndex, page, rows, rowCount, columnCount, sheet}; rows is an array of arrays of strings
chunks{chunkIndex, page, charStart, charEnd, text, citation: {type: "page", page, label}}
ocrUsedTrue for images
charCountLength of text
warningsNotes, for example that embedded pictures in a Word file were not read
extractedAtISO 8601 time

A file that fails returns {sourceUrl, documentId, error, errorType, extractedAt} instead, and is never charged.

In chunks, page is the 1-based unit number (an integer, so loaders built for PDFs work unchanged) and charStart and charEnd are offsets into that unit's text.

Units explained

File typeOne unit isCitation label example
DOCX, HTMLAbout 3,000 characters of text, split at paragraph boundariespart 2
PPTXOne slide that has text or a table (speaker notes included)slide 4
XLSXUp to 500 non-empty rows of one sheetSales rows 501-1000
CSVUp to 500 non-empty rowsrows 1-500
ImageOne image, or one frame of a multi-page TIFFimage, frame 2

Recipes: Office files for RAG, LangChain, pandas and OCR

Copy-paste starting points. Replace <APIFY_TOKEN> with your own token and the links with your files. The Python recipes are executed by tests/recipes_test.py against real output items of this Actor.

1. Word or PowerPoint to LangChain documents that cite a part or slide (pip install apify-client langchain-core)

from apify_client import ApifyClient
from langchain_core.documents import Document
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("landoz/documents-to-json-chunks").call(
run_input={"fileUrls": ["https://example.com/policy.docx", "https://example.com/deck.pptx"]}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
docs = [
Document(
page_content=chunk["text"],
metadata={"source": item["sourceUrl"], "file_type": item["fileType"], "where": chunk["citation"]["label"]},
)
for item in items
for chunk in item.get("chunks", []) # a file that failed is an item with "error" and no chunks
]

2. An Excel sheet or CSV to a pandas table (pip install apify-client pandas). Every sheet comes back in tables as rows of strings; the first row is usually the header.

import pandas as pd
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("landoz/documents-to-json-chunks").call(
run_input={"fileUrls": ["https://example.com/price-list.xlsx"]}
)
item = client.dataset(run["defaultDatasetId"]).list_items().items[0]
first = item["tables"][0]["rows"]
df = pd.DataFrame(first[1:], columns=first[0])

3. Read the text of a screenshot or scanned receipt. Run with {"fileUrls": ["https://example.com/receipt.png"]} and read text on the item. Images always go through OCR (English), $0.01 each on top of the $0.003 unit.

Why this one

The usual way this goes: python-docx handles the Word files, openpyxl the spreadsheets, something else the deck, and then a mislabelled file or a screenshot arrives and the afternoon is gone. Four libraries, four output shapes, and a chunk that cannot say which slide it came from.

One format for six file types. DOCX, PPTX, XLSX, CSV, HTML and images all come back as the same object, with the same chunk schema as the PDF and transcription Actors.

Citations that name the right thing. A slide is slide 4, a spreadsheet range is Sheet1 rows 1-500, a Word section is part 2. A retrieval answer can quote the slide number instead of the filename.

The type is read from the file, not the link. Links with no extension, or with the wrong one, still work.

Chunk boundaries. No chunk starts or ends on half a word. That holds by construction rather than by sampling: the chunker cuts at the last space when no sentence break is in reach, every Actor in this family carries a byte-identical copy of that file, and the build fails if a copy drifts.

Nothing is kept. The file is deleted as soon as it is parsed, and external images, scripts and links inside an HTML page are never fetched.

Tested every night against one fixed Word file and one fixed PNG.

Pricing in plain words

You pay per unit returned: $0.003 per unit, plus $0.01 per image read with OCR. Apify subscribers on paid plans pay less per unit (BRONZE $0.0027, SILVER $0.0024, GOLD and above $0.0021; OCR $0.009, $0.008, $0.007).

Two real runs, at list price. An Office batch of 9 units: $0.027. An image OCR batch of 3 OCR units: $0.039. Worked from the same event prices, a 20-page Word handbook is about 20 units at $0.06, a 30-slide deck $0.09, a 5,000-row price list 10 units at $0.03, and one screenshot $0.013.

Examples on the free plan:

  • A 20-page Word handbook (about 60,000 characters, 20 units): $0.06.
  • A 30-slide deck: $0.09.
  • A 5,000-row price list: 10 units, $0.03.
  • One screenshot or scanned receipt: $0.013.

The minimum "Maximum total charge" per run is $0.50. When a run reaches its maximum, the remaining units are not returned and not charged.

Never charged

  • Files that cannot be downloaded (HTTP 401, 403, 404, timeouts, network errors).
  • Unsupported, legacy, password-protected, corrupt or empty files.
  • Files over the size limit or over maxUnitsPerFile.
  • Units with no text and no table (blank slides, blank sheets, blank images).
  • Every error item ends with "Nothing was charged for this file."

Tips for best results

  • Links must return the file itself. A link without an extension is fine: the type is detected from the content.
  • For a big workbook, lower maxUnitsPerFile first to check the output and cost; a spreadsheet unit is 500 rows.
  • Legacy .doc, .xls and .ppt files are refused for free: save them as .docx, .xlsx or .pptx first.
  • Text inside images pasted into Word or PowerPoint is not read; export the slide or page as an image and pass that link instead.
  • Run PDFs through pdf-to-json-tables and recordings through transcribe-to-json-chunks: the chunk format is the same.

Limits

  • Legacy formats are not read: .doc, .xls, .ppt, .rtf, .odt, .ods, .odp and .heic return a free unsupported_format error that says how to convert (for example "save as .docx"). PDFs are pointed to pdf-to-json-tables.
  • No OCR of images embedded in Office files: a scanned page pasted into a Word file is not read (the item carries a warning).
  • English OCR only.
  • Charts, comments, headers and footers, text boxes in Word and formulas (only the last saved values) are not returned.
  • Macros are never run. Files over 200 MB unpacked or with more than 10,000 zip entries are refused as unsafe.
  • The Actor reads files by link only. It does not crawl or scrape websites.

Use it from an AI agent (Apify MCP server)

Connect your agent to https://mcp.apify.com. Then:

  1. Search for the tool: search-actors with "docx to json", "excel to json" or "office documents RAG".
  2. Read the schema: fetch-actor-details returns the input fields above and the dataset schema.
  3. Call it: call-actor with {"fileUrls": ["https://example.com/handbook.docx"]}.
  4. Read results with get-dataset-items. Index chunks[].text with citation.label and page as metadata.

The Actor charges only pay-per-event events, so it works with Apify's agentic payments.

Ready-made loaders for LangChain, LlamaIndex and a plain Python pipeline are in the examples repo: https://github.com/landoCommandoz/rag-ingestion-examples (they work with this Actor's output as is).

Open-source credits and licenses

ComponentRoleLicense
python-docxWord filesMIT
python-pptxPowerPoint filesMIT
openpyxlExcel filesMIT
Beautiful SoupHTMLMIT
lxmlXML and HTML parserBSD
PillowImagesHPND (MIT-CMU)
pytesseractPython bridge to TesseractApache-2.0
Tesseract OCR with engOCR engine (separate process)Apache-2.0
Apify SDK for JavaScript, got-scrapingActor runtime, downloadsApache-2.0
Base image apify/actor-node:22 (Node.js on Alpine Linux)RuntimeVarious open source

FAQ

Do links need a file extension? No. The type is read from the file itself.

Can I send a Google Docs or SharePoint link? Only a direct download link that works without a login. Export to .docx or .xlsx first.

How do I get one record per chunk? Loop over chunks in each item; every chunk carries its own citation. The examples repo does this for you.

My spreadsheet has 2,000 rows. How much? 4 units, $0.012.

Does it work with PDFs? Use pdf-to-json-tables; the output format is the same.

Can I run it on a schedule? Yes. Create a schedule in Apify Console with a fixed file link (for example a weekly price list) and add a webhook or an integration to send each run's dataset onward.

How do I call it from Python, Node.js or curl? See the Recipes section above. Any call that works with the Apify API works here.

Support

Open an issue on the Actor's Issues tab in Apify Console. Include the run id, the file link (if you can share it) and the input you used.